JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> != declaredType) {
useStaticTyping = true;
declaredType = secondary;
}
/* [JACKSON-114]: if using static typing, declared type is known
* to be the type...
*/
JsonSerialize.Typing typing = _annotationIntrospector.findSerializationTyping(a);
if (typing != null && typing != JsonSerialize.Typing.DEFAULT_TYPING) {
useStaticTyping = (typing == JsonSerialize.Typing.STATIC);
}
return useStaticTyping ? declaredType : null;
}
/*
/**********************************************************
/* Helper methods for default value handling
/**********************************************************
*/
protected Object getDefaultBean()
{
if (_defaultBean == null) {
/* If we can fix access rights, we should; otherwise non-public
* classes or default constructor will prevent instantiation
*/
_defaultBean = _beanDesc.instantiateBean(_config.canOverrideAccessModifiers());
if (_defaultBean == null) {
Class<?> cls = _beanDesc.getClassInfo().getAnnotated();
throw new IllegalArgumentException("Class "+cls.getName()+" has no default constructor; can not instantiate default bean value to support 'properties=JsonSerialize.Inclusion.NON_DEFAULT' annotation");
}
}
return _defaultBean;
}
protected Object getDefaultValue(String name, AnnotatedMember member)
{
Object defaultBean = getDefaultBean();
try {
return member.getValue(defaultBean);
} catch (Exception e) {
return _throwWrapped(e, name, defaultBean);
}
}
/*
/**********************************************************
/* Helper methods for exception handling
/**********************************************************
*/
protected Object _throwWrapped(Exception e, String propName, Object defaultBean)
{
Throwable t = e;
while (t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) throw (Error) t;
if (t instanceof RuntimeException) throw (RuntimeException) t;
throw new IllegalArgumentException("Failed to get property '"+propName+"' of default "+defaultBean.getClass().getName()+" instance");
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Class());
}
protected void _checkFailOnNumber(DeserializationContext ctxt) throws IOException
{
if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {
throw ctxt.mappingException("Not allowed to deserialize Enum value out of JSON number (disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow)");
}
}
/*
/**********************************************************
/* Additional helper classes
/**********************************************************
*/
/**
* Deserializer that uses a single-String static factory method
* for locating Enum values by String id.
*/
protected static class FactoryBasedDeserializer
extends StdDeserializer<Object>
implements ContextualDeserializer
{
private static final long serialVersionUID = 1;
// Marker type; null if String expected; otherwise numeric wrapper
protected final Class<?> _inputType;
protected final Method _factory;
protected final JsonDeserializer<?> _deser;
public FactoryBasedDeserializer(Class<?> cls, AnnotatedMethod f,
Class<?> inputType)
{
super(cls);
_factory = f.getAnnotated();
_inputType = inputType;
_deser = null;
}
protected FactoryBasedDeserializer(FactoryBasedDeserializer base,
JsonDeserializer<?> deser) {
super(base._valueClass);
_inputType = base._inputType;
_factory = base._factory;
_deser = deser;
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property)
throws JsonMappingException
{
if ((_deser == null) && (_inputType != String.class)) {
return new FactoryBasedDeserializer(this,
ctxt.findContextualValueDeserializer(ctxt.constructType(_inputType), property));
}
return this;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
Object value;
if (_deser != null) {
value = _deser.deserialize(jp, ctxt);
} else {
JsonToken curr = jp.getCurrentToken();
if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {
value = jp.getText();
} else {
value = jp.getValueAsString();
}
}
try {
return _factory.invoke(_valueClass, value);
} catch (Exception e) {
Throwable t = ClassUtil.getRootCause(e);
if (t instanceof IOException) {
throw (IOException) t;
}
throw ctxt.instantiationException(_valueClass, t);
}
}
@Override
public Object deserializeWithType(JsonParser jp, Deserialization
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.ser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* Intermediate base class for serializers used for serializing
* types that contain element(s) of other types, such as arrays,
* {@link java.util.Collection}s (<code>Lists</code>, <code>Sets</code>
* etc) and {@link java.util.Map}s and iterable things
* ({@link java.util.Iterator}s).
*/
@SuppressWarnings("serial")
public abstract class ContainerSerializer<T>
extends StdSerializer<T>
{
/*
/**********************************************************
/* Construction, initialization
/**********************************************************
*/
protected ContainerSerializer(Class<T> t) {
super(t);
}
/**
* @since 2.5
*/
protected ContainerSerializer(JavaType fullType) {
super(fullType);
}
/**
* Alternate constructor that is (alas!) needed to work
* around kinks of generic type handling
*
* @param t
*/
protected ContainerSerializer(Class<?> t, boolean dummy) {
super(t, dummy);
}
protected ContainerSerializer(ContainerSerializer<?> src) {
super(src._handledType, false);
}
/**
* Factory(-like) method that can be used to construct a new container
* serializer that uses specified {@link TypeSerializer} for decorating
* contained values with additional type information.
*
* @param vts Type serializer to use for contained values; can be null,
* in which case 'this' serializer is returned as is
* @return Serializer instance that uses given type serializer for values if
* that is possible (or if not, just 'this' serializer)
*/
public ContainerSerializer<?> withValueTypeSerializer(TypeSerializer vts) {
if (vts == null) return this;
return _withValueTypeSerializer(vts);
}
/*
/**********************************************************
/* Extended API
/**********************************************************
*/
/**
* Accessor for finding declared (static) element type for
* type this serializer is used for.
*/
public abstract JavaType getContentType();
/**
* Accessor for serializer used for serializing contents
* (List and array elements, Map values etc) of the
* container for which this serializer is used, if it is
* known statically.
* Note that for dynamic types this may return null
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>IgnoredPropertyNames() {
if (_ignoredPropertyNames == null) {
return Collections.emptySet();
}
return _ignoredPropertyNames;
}
@Override
public boolean hasKnownClassAnnotations() {
return _classInfo.hasAnnotations();
}
@Override
public Annotations getClassAnnotations() {
return _classInfo.getAnnotations();
}
@Override
public TypeBindings bindingsForBeanType()
{
if (_bindings == null) {
_bindings = new TypeBindings(_config.getTypeFactory(), _type);
}
return _bindings;
}
@Override
public JavaType resolveType(java.lang.reflect.Type jdkType) {
if (jdkType == null) {
return null;
}
return bindingsForBeanType().resolveType(jdkType);
}
@Override
public AnnotatedConstructor findDefaultConstructor() {
return _classInfo.getDefaultConstructor();
}
@Override
public AnnotatedMethod findAnySetter() throws IllegalArgumentException
{
if (_anySetterMethod != null) {
/* Also, let's be somewhat strict on how field name is to be
* passed; String, Object make sense, others not
* so much.
*/
/* !!! 18-May-2009, tatu: how about enums? Can add support if
* requested; easy enough for devs to add support within
* method.
*/
Class<?> type = _anySetterMethod.getRawParameterType(0);
if (type != String.class && type != Object.class) {
throw new IllegalArgumentException("Invalid 'any-setter' annotation on method "+_anySetterMethod.getName()+"(): first argument not of type String or Object, but "+type.getName());
}
}
return _anySetterMethod;
}
@Override
public Map<Object, AnnotatedMember> findInjectables() {
return _injectables;
}
@Override
public List<AnnotatedConstructor> getConstructors() {
return _classInfo.getConstructors();
}
@Override
public Object instantiateBean(boolean fixAccess)
{
AnnotatedConstructor ac = _classInfo.getDefaultConstructor();
if (ac == null) {
return null;
}
if (fixAccess) {
ac.fixAccess();
}
try {
return ac.getAnnotated().newInstance();
} catch (Exception e) {
Throwable t = e;
while (t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) throw (Error) t;
if (t instanceof RuntimeException) throw (RuntimeException) t;
throw new IllegalArgumentException("Failed to instantiate bean
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> of type "+_classInfo.getAnnotated().getName()+": ("+t.getClass().getName()+") "+t.getMessage(), t);
}
}
/*
/**********************************************************
/* Simple accessors, extended
/**********************************************************
*/
@Override
public AnnotatedMethod findMethod(String name, Class<?>[] paramTypes) {
return _classInfo.findMethod(name, paramTypes);
}
/*
/**********************************************************
/* General per-class annotation introspection
/**********************************************************
*/
@Override
public JsonFormat.Value findExpectedFormat(JsonFormat.Value defValue)
{
if (_annotationIntrospector != null) {
JsonFormat.Value v = _annotationIntrospector.findFormat(_classInfo);
if (v != null) {
return v;
}
}
return defValue;
}
/*
/**********************************************************
/* Introspection for serialization
/**********************************************************
*/
@Override
public Converter<Object,Object> findSerializationConverter()
{
if (_annotationIntrospector == null) {
return null;
}
return _createConverter(_annotationIntrospector.findSerializationConverter(_classInfo));
}
/**
* Method for determining whether null properties should be written
* out for a Bean of introspected type. This is based on global
* feature (lowest priority, passed as argument)
* and per-class annotation (highest priority).
*/
@Override
public JsonInclude.Include findSerializationInclusion(JsonInclude.Include defValue) {
if (_annotationIntrospector == null) {
return defValue;
}
return _annotationIntrospector.findSerializationInclusion(_classInfo, defValue);
}
@Override
public JsonInclude.Include findSerializationInclusionForContent(JsonInclude.Include defValue) {
if (_annotationIntrospector == null) {
return defValue;
}
return _annotationIntrospector.findSerializationInclusionForContent(_classInfo, defValue);
}
/**
* Method used to locate the method of introspected class that
* implements {@link com.fasterxml.jackson.annotation.JsonAnyGetter}.
* If no such method exists null is returned.
* If more than one are found, an exception is thrown.
*/
@Override
public AnnotatedMember findAnyGetter() throws IllegalArgumentException
{
if (_anyGetter != null) {
/* For now let's require a Map; in future can add support for other
* types like perhaps Iterable<Map.Entry>?
*/
Class<?> type = _anyGetter.getRawType();
if (!Map.class.isAssignableFrom(type)) {
throw new IllegalArgumentException("Invalid 'any-getter
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>(JsonParser p,
DeserializationContext ctxt, Object instance) throws IOException;
/**
* Method called to assign given value to this property, on
* specified Object.
*<p>
* Note: this is an optional operation, not supported by all
* implementations, creator-backed properties for example do not
* support this method.
*/
public abstract void set(Object instance, Object value) throws IOException;
/**
* Method called to assign given value to this property, on
* specified Object, and return whatever delegating accessor
* returned (if anything)
*<p>
* Note: this is an optional operation, not supported by all
* implementations, creator-backed properties for example do not
* support this method.
*/
public abstract Object setAndReturn(Object instance, Object value) throws IOException;
/**
* This method is needed by some specialized bean deserializers,
* and also called by some {@link #deserializeAndSet} implementations.
*<p>
* Pre-condition is that passed parser must point to the first token
* that should be consumed to produce the value (the only value for
* scalars, multiple for Objects and Arrays).
*<p>
* Note that this method is final for performance reasons: to override
* functionality you must override other methods that call this method;
* this method should also not be called directly unless you really know
* what you are doing (and probably not even then).
*/
public final Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
JsonToken t = p.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
return (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt);
}
if (_valueTypeDeserializer != null) {
return _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
}
return _valueDeserializer.deserialize(p, ctxt);
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
/**
* Method that takes in exception of any type, and casts or wraps it
* to an IOException or its subclass.
*/
protected void _throwAsIOE(Exception e, Object value) throws IOException
{
if (e instanceof IllegalArgumentException) {
String actType = (value == null) ? "[NULL]" : value.getClass().getName();
StringBuilder msg = new StringBuilder("Problem deserializing property '").append(getName());
msg.append("' (expected type: ").append(getType());
msg.append("; actual type: ").append(actType).append(")");
String origMsg = e.getMessage();
if (origMsg != null
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> if so.
*/
jp.nextToken();
jp.skipChildren();
continue;
}
// And then the value...
JsonToken t = jp.nextToken();
/* note: MUST check for nulls separately: deserializers will
* not handle them (and maybe fail or return bogus data)
*/
Object value;
try {
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
} catch (Exception e) {
wrapAndThrow(e, result, keyName);
return null;
}
result.put(key, value);
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
}
protected EnumMap<?,?> constructMap() {
return new EnumMap(_enumClass);
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
/**
* Bogus deserializer that will simply skip all content there is to map
* and returns Java null reference.
*
* @since 2.2
*/
public class NullifyingDeserializer
extends StdDeserializer<Object>
{
private static final long serialVersionUID = 1L;
public final static NullifyingDeserializer instance = new NullifyingDeserializer();
public NullifyingDeserializer() { super(Object.class); }
/*
/**********************************************************
/* Deserializer API
/**********************************************************
*/
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
jp.skipChildren();
return null;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// Not sure if we need to bother but:
JsonToken t = jp.getCurrentToken();
switch (t) {
case START_ARRAY:
case START_OBJECT:
case FIELD_NAME:
return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
default:
return null;
}
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> if (prob == null) {
prob = getRootCause(e);
}
}
if (prob instanceof RuntimeException) {
throw (RuntimeException) prob;
}
throw new ClassNotFoundException(prob.getMessage(), prob);
}
/*
/**********************************************************
/* Method type detection methods
/**********************************************************
*/
public static boolean hasGetterSignature(Method m)
{
// First: static methods can't be getters
if (Modifier.isStatic(m.getModifiers())) {
return false;
}
// Must take no args
Class<?>[] pts = m.getParameterTypes();
if (pts != null && pts.length != 0) {
return false;
}
// Can't be a void method
if (Void.TYPE == m.getReturnType()) {
return false;
}
// Otherwise looks ok:
return true;
}
/*
/**********************************************************
/* Exception handling
/**********************************************************
*/
/**
* Method that can be used to find the "root cause", innermost
* of chained (wrapped) exceptions.
*/
public static Throwable getRootCause(Throwable t)
{
while (t.getCause() != null) {
t = t.getCause();
}
return t;
}
/**
* Method that will unwrap root causes of given Throwable, and throw
* the innermost {@link Exception} or {@link Error} as is.
* This is useful in cases where mandatory wrapping is added, which
* is often done by Reflection API.
*/
public static void throwRootCause(Throwable t) throws Exception
{
t = getRootCause(t);
if (t instanceof Exception) {
throw (Exception) t;
}
throw (Error) t;
}
/**
* Method that will wrap 't' as an {@link IllegalArgumentException} if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void throwAsIAE(Throwable t)
{
throwAsIAE(t, t.getMessage());
}
/**
* Method that will wrap 't' as an {@link IllegalArgumentException} (and with
* specified message) if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void throwAsIAE(Throwable t, String msg)
{
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
if (t instanceof Error) {
throw (Error) t;
}
throw new IllegalArgumentException(msg, t);
}
/**
* Method that will locate the innermost exception for given Throwable;
* and then wrap it as an {@link
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> IllegalArgumentException} if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void unwrapAndThrowAsIAE(Throwable t)
{
throwAsIAE(getRootCause(t));
}
/**
* Method that will locate the innermost exception for given Throwable;
* and then wrap it as an {@link IllegalArgumentException} if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void unwrapAndThrowAsIAE(Throwable t, String msg)
{
throwAsIAE(getRootCause(t), msg);
}
/*
/**********************************************************
/* Instantiation
/**********************************************************
*/
/**
* Method that can be called to try to create an instantiate of
* specified type. Instantiation is done using default no-argument
* constructor.
*
* @param canFixAccess Whether it is possible to try to change access
* rights of the default constructor (in case it is not publicly
* accessible) or not.
*
* @throws IllegalArgumentException If instantiation fails for any reason;
* except for cases where constructor throws an unchecked exception
* (which will be passed as is)
*/
public static <T> T createInstance(Class<T> cls, boolean canFixAccess)
throws IllegalArgumentException
{
Constructor<T> ctor = findConstructor(cls, canFixAccess);
if (ctor == null) {
throw new IllegalArgumentException("Class "+cls.getName()+" has no default (no arg) constructor");
}
try {
return ctor.newInstance();
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+cls.getName()+", problem: "+e.getMessage());
return null;
}
}
public static <T> Constructor<T> findConstructor(Class<T> cls, boolean canFixAccess)
throws IllegalArgumentException
{
try {
Constructor<T> ctor = cls.getDeclaredConstructor();
if (canFixAccess) {
checkAndFixAccess(ctor);
} else {
// Has to be public...
if (!Modifier.isPublic(ctor.getModifiers())) {
throw new IllegalArgumentException("Default constructor for "+cls.getName()+" is not accessible (non-public?): not allowed to try modify access via Reflection: can not instantiate type");
}
}
return ctor;
} catch (NoSuchMethodException e) {
;
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e, "Failed to find default constructor of class "+cls.getName()+", problem: "+e.getMessage());
}
return null;
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>class);
enumMapTypeField = locateField(EnumMap.class, "elementType", Class.class);
}
@SuppressWarnings("unchecked")
public Class<? extends Enum<?>> enumTypeFor(EnumSet<?> set)
{
if (enumSetTypeField != null) {
return (Class<? extends Enum<?>>) get(set, enumSetTypeField);
}
throw new IllegalStateException("Can not figure out type for EnumSet (odd JDK platform?)");
}
@SuppressWarnings("unchecked")
public Class<? extends Enum<?>> enumTypeFor(EnumMap<?,?> set)
{
if (enumMapTypeField != null) {
return (Class<? extends Enum<?>>) get(set, enumMapTypeField);
}
throw new IllegalStateException("Can not figure out type for EnumMap (odd JDK platform?)");
}
private Object get(Object bean, Field field)
{
try {
return field.get(bean);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private static Field locateField(Class<?> fromClass, String expectedName, Class<?> type)
{
Field found = null;
// First: let's see if we can find exact match:
Field[] fields = fromClass.getDeclaredFields();
for (Field f : fields) {
if (expectedName.equals(f.getName()) && f.getType() == type) {
found = f;
break;
}
}
// And if not, if there is just one field with the type, that field
if (found == null) {
for (Field f : fields) {
if (f.getType() == type) {
// If more than one, can't choose
if (found != null) return null;
found = f;
}
}
}
if (found != null) { // it's non-public, need to force accessible
try {
found.setAccessible(true);
} catch (Throwable t) { }
}
return found;
}
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>jp, SAMPLE_SPEC_VALUE_TN_HEIGHT);
}
assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width'
if (verifyContents) {
verifyFieldName(jp, "Width");
}
// Width value is actually a String in the example
assertToken(JsonToken.VALUE_STRING, jp.nextToken());
if (verifyContents) {
assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, getAndVerifyText(jp));
}
assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'thumbnail' object
assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'IDs'
assertToken(JsonToken.START_ARRAY, jp.nextToken()); // 'ids' array
verifyIntToken(jp.nextToken(), requireNumbers); // ids[0]
if (verifyContents) {
verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID1);
}
verifyIntToken(jp.nextToken(), requireNumbers); // ids[1]
if (verifyContents) {
verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID2);
}
verifyIntToken(jp.nextToken(), requireNumbers); // ids[2]
if (verifyContents) {
verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID3);
}
verifyIntToken(jp.nextToken(), requireNumbers); // ids[3]
if (verifyContents) {
verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID4);
}
assertToken(JsonToken.END_ARRAY, jp.nextToken()); // 'ids' array
assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'image' object
assertToken(JsonToken.END_OBJECT, jp.nextToken()); // main object
}
private void verifyIntToken(JsonToken t, boolean requireNumbers)
{
if (t == JsonToken.VALUE_NUMBER_INT) {
return;
}
if (requireNumbers) { // to get error
assertToken(JsonToken.VALUE_NUMBER_INT, t);
}
// if not number, must be String
if (t != JsonToken.VALUE_STRING) {
fail("Expected INT or STRING value, got "+t);
}
}
protected void verifyFieldName(JsonParser jp, String expName)
throws IOException
{
assertEquals(expName, jp.getText());
assertEquals(expName, jp.getCurrentName());
}
protected void verifyIntValue(JsonParser jp, long expValue)
throws IOException
{
// First, via textual
assertEquals(String.valueOf(expValue
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>) {
Object ob = typeDeserializer.deserializeTypedFromObject(p, ctxt);
return _handleTypedObjectId(p, ctxt, ob, id);
}
}
// or, Object Ids Jackson explicitly sets
JsonToken t = p.getCurrentToken();
if (t != null) {
// Most commonly, a scalar (int id, uuid String, ...)
if (t.isScalarValue()) {
return deserializeFromObjectId(p, ctxt);
}
// but, with 2.5+, a simple Object-wrapped value also legal:
if (t == JsonToken.START_OBJECT) {
t = p.nextToken();
}
if (t == JsonToken.FIELD_NAME && _objectIdReader.maySerializeAsObject()
&& _objectIdReader.isValidReferencePropertyName(p.getCurrentName(), p)) {
return deserializeFromObjectId(p, ctxt);
}
}
}
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromObject(p, ctxt);
}
/**
* Offlined method called to handle "native" Object Id that has been read
* and known to be associated with given deserialized POJO.
*
* @since 2.3
*/
protected Object _handleTypedObjectId(JsonParser jp, DeserializationContext ctxt,
Object pojo, Object rawId)
throws IOException
{
/* 07-Aug-2013, tatu: One more challenge: type of id may not be type
* of property we are expecting later on; specifically, numeric ids
* vs Strings.
*/
JsonDeserializer<Object> idDeser = _objectIdReader.getDeserializer();
final Object id;
// Ok, this is bit ridiculous; let's see if conversion is needed:
if (idDeser.handledType() == rawId.getClass()) {
// nope: already same type
id = rawId;
} else {
id = _convertObjectId(jp, ctxt, rawId, idDeser);
}
ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver);
roid.bindItem(pojo);
// also: may need to set a property value as well
SettableBeanProperty idProp = _objectIdReader.idProperty;
if (idProp != null) {
return idProp.setAndReturn(pojo, id);
}
return pojo;
}
/**
* Helper method we need to do necessary conversion from whatever native object id
* type is, into declared type that Jackson internals expect. This may be
* simple
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Context ctxt) throws IOException
{
if (_delegateDeserializer != null) {
try {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
}
} else if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
return null;
}
final Object value = deserialize(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
}
return value;
} else if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
throw ctxt.mappingException(handledType(), JsonToken.START_ARRAY);
}
throw ctxt.mappingException(handledType());
}
public Object deserializeFromEmbedded(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// First things first: id Object Id is used, most likely that's it; specifically,
// true for UUIDs when written as binary (with Smile, other binary formats)
if (_objectIdReader != null) {
return deserializeFromObjectId(jp, ctxt);
}
// TODO: maybe add support for ValueInstantiator, embedded?
return jp.getEmbeddedObject();
}
/*
/**********************************************************
/* Overridable helper methods
/**********************************************************
*/
protected void injectValues(DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
for (ValueInjector injector : _injectables) {
injector.inject(ctxt, bean);
}
}
/**
* Method called to handle set of one or more unknown properties,
* stored in their entirety in given {@link TokenBuffer}
* (as field entries, name and value).
*/
@SuppressWarnings("resource")
protected Object handleUnknownProperties(DeserializationContext ctxt,
Object bean, TokenBuffer unknownTokens)
throws IOException, JsonProcessingException
{
// First: add closing END_OBJECT as marker
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> type = ctxt.constructType(bean.getClass());
/* 30-Jan-2012, tatu: Ideally we would be passing referring
* property; which in theory we could keep track of via
* ResolvableDeserializer (if we absolutely must...).
* But for now, let's not bother.
*/
// subDeser = ctxt.findValueDeserializer(type, _property);
subDeser = ctxt.findRootValueDeserializer(type);
// Also, need to cache it
if (subDeser != null) {
synchronized (this) {
if (_subDeserializers == null) {
_subDeserializers = new HashMap<ClassKey,JsonDeserializer<Object>>();;
}
_subDeserializers.put(new ClassKey(bean.getClass()), subDeser);
}
}
return subDeser;
}
/*
/**********************************************************
/* Helper methods for error reporting
/**********************************************************
*/
/**
* Method that will modify caught exception (passed in as argument)
* as necessary to include reference information, and to ensure it
* is a subtype of {@link IOException}, or an unchecked exception.
*<p>
* Rules for wrapping and unwrapping are bit complicated; essentially:
*<ul>
* <li>Errors are to be passed as is (if uncovered via unwrapping)
* <li>"Plain" IOExceptions (ones that are not of type
* {@link JsonMappingException} are to be passed as is
*</ul>
*/
public void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)
throws IOException
{
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt), bean, fieldName);
}
@Deprecated // since 2.4, not used by core Jackson; only relevant for arrays/Collections
public void wrapAndThrow(Throwable t, Object bean, int index, DeserializationContext ctxt) throws IOException {
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt), bean, index);
}
private Throwable throwOrReturnThrowable(Throwable t, DeserializationContext ctxt)
throws IOException
{
/* 05-Mar-2009, tatu: But one nasty edge is when we get
* StackOverflow: usually due to infinite loop. But that
* often gets hidden within an InvocationTargetException...
*/
while (t instanceof InvocationTargetException && t.getCause() != null) {
t
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> = t.getCause();
}
// Errors to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
// Ditto for IOExceptions; except we may want to wrap JSON exceptions
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonProcessingException)) {
throw (IOException) t;
}
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
}
return t;
}
protected void wrapInstantiationProblem(Throwable t, DeserializationContext ctxt)
throws IOException
{
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
if (t instanceof IOException) {
// Since we have no more information to add, let's not actually wrap..
throw (IOException) t;
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
}
throw ctxt.instantiationException(_beanType.getRawClass(), t);
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>valueDeserializer;
}
/*
/**********************************************************
/* JsonDeserializer API
/**********************************************************
*/
/**
* Turns out that these are expensive enough to create so that caching
* does make sense.
*<p>
* IMPORTANT: but, note, that instances CAN NOT BE CACHED if there is
* a value type deserializer; this caused an issue with 2.4.4 of
* JAXB Annotations (failing a test).
* It is also possible that some other settings could make deserializers
* un-cacheable; but on the other hand, caching can make a big positive
* difference with performance... so it's a hard choice.
*
* @since 2.4.4
*/
@Override
public boolean isCachable() {
/* As per [databind#735], existence of value or key deserializer (only passed
* if annotated to use non-standard one) should also prevent caching.
*/
return (_valueDeserializer == null)
&& (_keyDeserializer == null)
&& (_valueTypeDeserializer == null)
&& (_ignorableProperties == null);
}
@Override
@SuppressWarnings("unchecked")
public Map<Object,Object> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_propertyBasedCreator != null) {
return _deserializeUsingCreator(jp, ctxt);
}
if (_delegateDeserializer != null) {
return (Map<Object,Object>) _valueInstantiator.createUsingDelegate(ctxt,
_delegateDeserializer.deserialize(jp, ctxt));
}
if (!_hasDefaultCreator) {
throw ctxt.instantiationException(getMapClass(), "No default constructor found");
}
// Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
JsonToken t = jp.getCurrentToken();
if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) {
// [JACKSON-620] (empty) String may be ok however:
if (t == JsonToken.VALUE_STRING) {
return (Map<Object,Object>) _valueInstantiator.createFromString(ctxt, jp.getText());
}
// slightly redundant (since String was passed above), but
return _deserializeFromEmpty(jp, ctxt);
}
final Map<Object,Object> result = (Map<Object,Object>) _valueInstantiator.createUsingDefault(ctxt);
if (_standardStringKey) {
_readAndBindStringMap(jp, ctxt, result);
return result;
}
_readAndBind(jp, ctxt
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>, result);
return result;
}
@Override
public Map<Object,Object> deserialize(JsonParser p, DeserializationContext ctxt,
Map<Object,Object> result)
throws IOException
{
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(result);
// Ok: must point to START_OBJECT or FIELD_NAME
JsonToken t = p.getCurrentToken();
if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME) {
throw ctxt.mappingException(getMapClass());
}
if (_standardStringKey) {
_readAndBindStringMap(p, ctxt, result);
return result;
}
_readAndBind(p, ctxt, result);
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
}
/*
/**********************************************************
/* Other public accessors
/**********************************************************
*/
@SuppressWarnings("unchecked")
public final Class<?> getMapClass() { return (Class<Map<Object,Object>>) _mapType.getRawClass(); }
@Override public JavaType getValueType() { return _mapType; }
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected final void _readAndBind(JsonParser jp, DeserializationContext ctxt,
Map<Object,Object> result)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
final KeyDeserializer keyDes = _keyDeserializer;
final JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
MapReferringAccumulator referringAccumulator = null;
boolean useObjectId = valueDes.getObjectIdReader() != null;
if (useObjectId) {
referringAccumulator = new MapReferringAccumulator(_mapType.getContentType().getRawClass(), result);
}
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
// Must point to field name
String fieldName = jp.getCurrentName();
Object key = keyDes.deserializeKey(fieldName, ctxt);
// And then the value...
t = jp.nextToken();
if (_ignorableProperties != null && _ignorableProperties.contains(fieldName)) {
jp.skipChildren();
continue;
}
try{
// Note
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>: must handle null explicitly here; value deserializers won't
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
/* !!! 23-Dec-2008, tatu: should there be an option to verify
* that there are no duplicate field names? (and/or what
* to do, keep-first or keep-last)
*/
if (useObjectId) {
referringAccumulator.put(key, value);
} else {
result.put(key, value);
}
} catch (UnresolvedForwardReference reference) {
handleUnresolvedReference(jp, referringAccumulator, key, reference);
} catch (Exception e) {
wrapAndThrow(e, result, fieldName);
}
}
}
/**
* Optimized method used when keys can be deserialized as plain old
* {@link java.lang.String}s, and there is no custom deserialized
* specified.
*/
protected final void _readAndBindStringMap(JsonParser jp, DeserializationContext ctxt,
Map<Object,Object> result)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
final JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
MapReferringAccumulator referringAccumulator = null;
boolean useObjectId = valueDes.getObjectIdReader() != null;
if (useObjectId) {
referringAccumulator = new MapReferringAccumulator(_mapType.getContentType().getRawClass(), result);
}
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
// Must point to field name
String fieldName = jp.getCurrentName();
// And then the value...
t = jp.nextToken();
if (_ignorableProperties != null && _ignorableProperties.contains(fieldName)) {
jp.skipChildren();
continue;
}
try {
// Note: must handle null explicitly here; value deserializers won't
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
}
if (useObjectId) {
referringAccumulator.put(fieldName, value);
} else {
result.put(fieldName, value);
}
} catch (UnresolvedForwardReference reference) {
handleUnresolvedReference(jp, referringAccumulator, fieldName, reference);
} catch (Exception e) {
wrapAndThrow(e, result, fieldName);
}
}
}
@SuppressWarnings("unchecked")
public Map<Object,Object> _deserializeUsingCreator(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
// null -> no ObjectIdReader for Maps (yet?)
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, null);
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
final JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
t = jp.nextToken(); // to get to value
if (_ignorableProperties != null && _ignorableProperties.contains(propName)) {
jp.skipChildren(); // and skip it (in case of array/object)
continue;
}
// creator property?
SettableBeanProperty prop = creator.findCreatorProperty(propName);
if (prop != null) {
// Last property to set?
Object value = prop.deserialize(jp, ctxt);
if (buffer.assignParameter(prop.getCreatorIndex(), value)) {
jp.nextToken();
Map<Object,Object> result;
try {
result = (Map<Object,Object>)creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _mapType.getRawClass(), propName);
return null;
}
_readAndBind(jp, ctxt, result);
return result;
}
continue;
}
// other property? needs buffering
String fieldName = jp.getCurrentName();
Object key = _keyDeserializer.deserializeKey(fieldName, ctxt);
Object value;
try {
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
} catch (Exception e) {
wrapAndThrow(e, _
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>mapType.getRawClass(), propName);
return null;
}
buffer.bufferMapProperty(key, value);
}
// end of JSON object?
// if so, can just construct and leave...
try {
return (Map<Object,Object>)creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _mapType.getRawClass(), null);
return null;
}
}
@Deprecated // since 2.5
protected void wrapAndThrow(Throwable t, Object ref) throws IOException {
wrapAndThrow(t, ref, null);
}
private void handleUnresolvedReference(JsonParser jp, MapReferringAccumulator accumulator,
Object key, UnresolvedForwardReference reference)
throws JsonMappingException
{
if (accumulator == null) {
throw JsonMappingException.from(jp, "Unresolved forward reference but no identity info.", reference);
}
Referring referring = accumulator.handleUnresolvedReference(reference, key);
reference.getRoid().appendReferring(referring);
}
private final static class MapReferringAccumulator {
private final Class<?> _valueType;
private Map<Object,Object> _result;
/**
* A list of {@link MapReferring} to maintain ordering.
*/
private List<MapReferring> _accumulator = new ArrayList<MapReferring>();
public MapReferringAccumulator(Class<?> valueType, Map<Object, Object> result) {
_valueType = valueType;
_result = result;
}
public void put(Object key, Object value)
{
if (_accumulator.isEmpty()) {
_result.put(key, value);
} else {
MapReferring ref = _accumulator.get(_accumulator.size() - 1);
ref.next.put(key, value);
}
}
public Referring handleUnresolvedReference(UnresolvedForwardReference reference, Object key)
{
MapReferring id = new MapReferring(this, reference, _valueType, key);
_accumulator.add(id);
return id;
}
public void resolveForwardReference(Object id, Object value) throws IOException
{
Iterator<MapReferring> iterator = _accumulator.iterator();
// Resolve ordering after resolution of an id. This means either:
// 1- adding to the result map in case of the first unresolved id.
// 2- merge the content of the resolved id with its previous unresolved id.
Map<Object,Object> previous = _result;
while (iterator.hasNext()) {
MapReferring ref = iterator.next();
if (ref.hasId(id)) {
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> _buildMethod = src._buildMethod;
}
public BuilderBasedDeserializer(BuilderBasedDeserializer src, HashSet<String> ignorableProps) {
super(src, ignorableProps);
_buildMethod = src._buildMethod;
}
@Override
public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
{
/* main thing really is to just enforce ignoring of unknown
* properties; since there may be multiple unwrapped values
* and properties for all may be interleaved...
*/
return new BuilderBasedDeserializer(this, unwrapper);
}
@Override
public BuilderBasedDeserializer withObjectIdReader(ObjectIdReader oir) {
return new BuilderBasedDeserializer(this, oir);
}
@Override
public BuilderBasedDeserializer withIgnorableProperties(HashSet<String> ignorableProps) {
return new BuilderBasedDeserializer(this, ignorableProps);
}
@Override
protected BeanAsArrayBuilderDeserializer asArrayDeserializer() {
SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
return new BeanAsArrayBuilderDeserializer(this, props, _buildMethod);
}
/*
/**********************************************************
/* JsonDeserializer implementation
/**********************************************************
*/
protected final Object finishBuild(DeserializationContext ctxt, Object builder)
throws IOException
{
try {
return _buildMethod.getMember().invoke(builder);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null;
}
}
/**
* Main deserialization method for bean-based objects (POJOs).
*/
@Override
public final Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
// common case first:
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
if (_vanillaProcessing) {
return finishBuild(ctxt, vanillaDeserialize(jp, ctxt, t));
}
Object builder = deserializeFromObject(jp, ctxt);
return finishBuild(ctxt, builder);
}
// and then others, generally requiring use of @JsonCreator
switch (t) {
case VALUE_STRING:
return finishBuild(ctxt, deserializeFromString(jp, ctxt));
case VALUE_NUMBER_INT:
return finishBuild(ctxt, deserializeFromNumber(jp, ctxt));
case VALUE_NUMBER_FLOAT:
return finishBuild(ctxt, deserializeFromDouble(jp, ctxt));
case VALUE_EMBEDDED_OBJECT:
return jp.getEmbeddedObject();
case VALUE_TRUE:
case VALUE_FALSE:
return finishBuild(ctxt, deserializeFromBoolean(jp,
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> ctxt));
case START_ARRAY:
// these only work if there's a (delegating) creator...
return finishBuild(ctxt, deserializeFromArray(jp, ctxt));
case FIELD_NAME:
case END_OBJECT: // added to resolve [JACKSON-319], possible related issues
return finishBuild(ctxt, deserializeFromObject(jp, ctxt));
default:
throw ctxt.mappingException(handledType());
}
}
/**
* Secondary deserialization method, called in cases where POJO
* instance is created as part of deserialization, potentially
* after collecting some or all of the properties to set.
*/
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt,
Object builder)
throws IOException, JsonProcessingException
{
/* Important: we call separate method which does NOT call
* 'finishBuild()', to avoid problems with recursion
*/
return finishBuild(ctxt, _deserialize(jp, ctxt, builder));
}
/*
/**********************************************************
/* Concrete deserialization methods
/**********************************************************
*/
protected final Object _deserialize(JsonParser jp,
DeserializationContext ctxt, Object builder)
throws IOException, JsonProcessingException
{
if (_injectables != null) {
injectValues(ctxt, builder);
}
if (_unwrappedPropertyHandler != null) {
return deserializeWithUnwrapped(jp, ctxt, builder);
}
if (_externalTypeIdHandler != null) {
return deserializeWithExternalTypeId(jp, ctxt, builder);
}
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(jp, ctxt, builder, view);
}
}
JsonToken t = jp.getCurrentToken();
// 23-Mar-2010, tatu: In some cases, we start with full JSON object too...
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
builder = prop.deserializeSetAndReturn(jp, ctxt, builder);
} catch (Exception e) {
wrapAndThrow(e, builder, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, handledType(), propName);
}
return builder;
}
/**
* Streamlined
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> version that is only used when no "special"
* features are enabled.
*/
private final Object vanillaDeserialize(JsonParser jp,
DeserializationContext ctxt, JsonToken t)
throws IOException, JsonProcessingException
{
Object bean = _valueInstantiator.createUsingDefault(ctxt);
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
} else {
handleUnknownVanilla(jp, ctxt, bean, propName);
}
}
return bean;
}
/**
* General version used when handling needs more advanced
* features.
*/
@Override
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_nonStandardCreation) {
if (_unwrappedPropertyHandler != null) {
return deserializeWithUnwrapped(jp, ctxt);
}
if (_externalTypeIdHandler != null) {
return deserializeWithExternalTypeId(jp, ctxt);
}
return deserializeFromObjectUsingNonDefault(jp, ctxt);
}
Object bean = _valueInstantiator.createUsingDefault(ctxt);
if (_injectables != null) {
injectValues(ctxt, bean);
}
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(jp, ctxt, bean, view);
}
}
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, bean, propName);
}
return bean;
}
/**
* Method called to deserialize bean using "property-based creator":
* this means that a non-default constructor or factory method is
* called, and then possibly other setters. The trick
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> is that
* values for creator method need to be buffered, first; and
* due to non-guaranteed ordering possibly some other properties
* as well.
*/
@Override
@SuppressWarnings("resource")
protected final Object _deserializeUsingPropertyBased(final JsonParser jp,
final DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
// 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
TokenBuffer unknown = null;
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; // never gets here
}
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(jp, ctxt, bean, unknown);
}
if (unknown != null) { // nope, just extra unknown stuff...
bean = handleUnknownProperties(ctxt, bean, unknown);
}
// or just clean?
return _deserialize(jp, ctxt, bean);
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(jp, ctxt));
continue;
}
// As per [JACKSON-313], things marked as ignorable should not be
// passed to any setter
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, handledType(), propName);
continue;
}
// "any property"?
if (_anySetter != null)
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt));
continue;
}
// Ok then, let's collect the whole field; name and value
if (unknown == null) {
unknown = new TokenBuffer(jp);
}
unknown.writeFieldName(propName);
unknown.copyCurrentStructure(jp);
}
// We hit END_OBJECT, so:
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null; // never gets here
}
if (unknown != null) {
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(null, ctxt, bean, unknown);
}
// no, just some extra unknown properties
return handleUnknownProperties(ctxt, bean, unknown);
}
return bean;
}
/*
/**********************************************************
/* Deserializing when we have to consider an active View
/**********************************************************
*/
protected final Object deserializeWithView(JsonParser jp, DeserializationContext ctxt,
Object bean, Class<?> activeView)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
if (!prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, bean, propName);
}
return bean;
}
/*
/**********************************************************
/* Handling for cases where we have "unwrapped" values
/**********************************************************
*/
/**
* Method called when there are declared "unwrapped" properties
* which need special handling
*/
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
}
if (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithUnwrapped(jp, ctxt);
}
TokenBuffer
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> tokens = new TokenBuffer(jp);
tokens.writeStartObject();
Object bean = _valueInstantiator.createUsingDefault(ctxt);
if (_injectables != null) {
injectValues(ctxt, bean);
}
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// ignorable things should be ignored
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
try {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser jp,
DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
SettableBeanProperty prop = _beanProperties.find(propName);
jp.nextToken();
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView))
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> {
jp.skipChildren();
continue;
}
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser jp,
DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
t = jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; // never gets here
}
// if so, need to copy all remaining tokens into buffer
while (t == JsonToken.FIELD_NAME) {
jp.nextToken(); // to skip name
tokens.copyCurrentStructure(jp);
t = jp.nextToken();
}
tokens.writeEndObject();
if (bean.getClass() != _beanType.getRawClass()) {
// !!! 08-Jul-2011, tatu: Could probably support; but for now
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> getAnnotation(Class<A> acls) {
return _annotated.getAnnotation(acls);
}
@Override public AnnotatedMember getMember() { return _annotated; }
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override
public final void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
/* Hmmh. Is this a problem? We won't be setting anything, so it's
* equivalent of empty Collection/Map in this case
*/
return;
}
// For [#501] fix we need to implement this but:
if (_valueTypeDeserializer != null) {
throw new JsonMappingException("Problem deserializing 'setterless' property (\""+getName()+"\"): no way to handle typed deser with setterless yet");
// return _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
}
// Ok: then, need to fetch Collection/Map to modify:
Object toModify;
try {
toModify = _getter.invoke(instance);
} catch (Exception e) {
_throwAsIOE(e);
return; // never gets here
}
/* Note: null won't work, since we can't then inject anything
* in. At least that's not good in common case. However,
* theoretically the case where we get JSON null might
* be compatible. If so, implementation could be changed.
*/
if (toModify == null) {
throw new JsonMappingException("Problem deserializing 'setterless' property '"+getName()+"': get method returned null");
}
_valueDeserializer.deserialize(jp, ctxt, toModify);
}
@Override
public Object deserializeSetAndReturn(JsonParser jp,
DeserializationContext ctxt, Object instance) throws IOException, JsonProcessingException
{
deserializeAndSet(jp, ctxt, instance);
return instance;
}
@Override
public final void set(Object instance, Object value) throws IOException {
throw new UnsupportedOperationException("Should never call 'set' on setterless property");
}
@Override
public Object setAndReturn(Object instance, Object value) throws IOException
{
set(instance, value);
return null;
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>}s.
*
* @since 2.3
*/
public static AbstractDeserializer constructForNonPOJO(BeanDescription beanDesc) {
return new AbstractDeserializer(beanDesc);
}
/*
/**********************************************************
/* Public accessors
/**********************************************************
*/
@Override
public Class<?> handledType() {
return _baseType.getRawClass();
}
@Override
public boolean isCachable() { return true; }
/**
* Overridden to return true for those instances that are
* handling value for which Object Identity handling is enabled
* (either via value type or referring property).
*/
@Override
public ObjectIdReader getObjectIdReader() {
return _objectIdReader;
}
/**
* Method called by <code>BeanDeserializer</code> to resolve back reference
* part of managed references.
*/
@Override
public SettableBeanProperty findBackReference(String logicalName) {
return (_backRefProperties == null) ? null : _backRefProperties.get(logicalName);
}
/*
/**********************************************************
/* Deserializer implementation
/**********************************************************
*/
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// Hmmh. One tricky question; for scalar, is it an Object Id, or "Natural" type?
// for now, prefer Object Id:
if (_objectIdReader != null) {
JsonToken t = jp.getCurrentToken();
// should be good enough check; we only care about Strings, integral numbers:
if (t != null && t.isScalarValue()) {
return _deserializeFromObjectId(jp, ctxt);
}
}
// First: support "natural" values (which are always serialized without type info!)
Object result = _deserializeIfNatural(jp, ctxt);
if (result != null) {
return result;
}
return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// This method should never be called...
throw ctxt.instantiationException(_baseType.getRawClass(),
"abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information");
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected Object _deserializeIfNatural(JsonParser jp, DeserializationContext ctxt) throws IOException
{
/* As per [JACKSON-417], there is a chance we might be "natural" types
* (String, Boolean, Integer, Double
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> withContenValueHandler()");
}
@Override
public SimpleType withStaticTyping() {
return _asStatic ? this : new SimpleType(_class,
_typeNames, _typeParameters, _valueHandler, _typeHandler, _asStatic, _typeParametersFor);
}
@Override
protected String buildCanonicalName()
{
StringBuilder sb = new StringBuilder();
sb.append(_class.getName());
if (_typeParameters != null && _typeParameters.length > 0) {
sb.append('<');
boolean first = true;
for (JavaType t : _typeParameters) {
if (first) {
first = false;
} else {
sb.append(',');
}
sb.append(t.toCanonical());
}
sb.append('>');
}
return sb.toString();
}
/*
/**********************************************************
/* Public API
/**********************************************************
*/
@Override
public boolean isContainerType() { return false; }
@Override
public int containedTypeCount() {
return (_typeParameters == null) ? 0 : _typeParameters.length;
}
@Override
public JavaType containedType(int index)
{
if (index < 0 || _typeParameters == null || index >= _typeParameters.length) {
return null;
}
return _typeParameters[index];
}
@Override
public String containedTypeName(int index)
{
if (index < 0 || _typeNames == null || index >= _typeNames.length) {
return null;
}
return _typeNames[index];
}
@Override
public Class<?> getParameterSource() {
return _typeParametersFor;
}
@Override
public StringBuilder getErasedSignature(StringBuilder sb) {
return _classSignature(_class, sb, true);
}
@Override
public StringBuilder getGenericSignature(StringBuilder sb)
{
_classSignature(_class, sb, false);
if (_typeParameters != null) {
sb.append('<');
for (JavaType param : _typeParameters) {
sb = param.getGenericSignature(sb);
}
sb.append('>');
}
sb.append(';');
return sb;
}
/*
/**********************************************************
/* Standard methods
/**********************************************************
*/
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(40);
sb.append("[simple type, class ").append(buildCanonicalName()).append(']');
return sb.toString();
}
@Override
public boolean equals(Object o)
{
if (o == this) return true;
if (o == null) return false
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> new InnerClassProperty(this, deser);
}
// // // BeanProperty impl
@Override
public <A extends Annotation> A getAnnotation(Class<A> acls) {
return _delegate.getAnnotation(acls);
}
@Override public AnnotatedMember getMember() { return _delegate.getMember(); }
/*
/**********************************************************
/* Deserialization methods
/**********************************************************
*/
@Override
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, Object bean)
throws IOException
{
JsonToken t = jp.getCurrentToken();
Object value;
if (t == JsonToken.VALUE_NULL) {
value = (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt);
} else if (_valueTypeDeserializer != null) {
value = _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
} else { // the usual case
try {
value = _creator.newInstance(bean);
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+_creator.getDeclaringClass().getName()+", problem: "+e.getMessage());
value = null;
}
_valueDeserializer.deserialize(jp, ctxt, value);
}
set(bean, value);
}
@Override
public Object deserializeSetAndReturn(JsonParser jp,
DeserializationContext ctxt, Object instance)
throws IOException
{
return setAndReturn(instance, deserialize(jp, ctxt));
}
@Override
public final void set(Object instance, Object value) throws IOException {
_delegate.set(instance, value);
}
@Override
public Object setAndReturn(Object instance, Object value) throws IOException {
return _delegate.setAndReturn(instance, value);
}
/*
/**********************************************************
/* JDK serialization handling
/**********************************************************
*/
// When reading things back,
Object readResolve() {
return new InnerClassProperty(this, _annotated);
}
Object writeReplace() {
// need to construct a fake instance to support serialization
if (_annotated != null) {
return this;
}
return new InnerClassProperty(this, new AnnotatedConstructor(null, _creator, null, null));
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> return _valueDeserializer;
}
/*
/**********************************************************
/* JsonDeserializer API
/**********************************************************
*/
@Override
public Map.Entry<Object,Object> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
JsonToken t = jp.getCurrentToken();
if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) {
// [JACKSON-620] (empty) String may be ok however:
// slightly redundant (since String was passed above), but
return _deserializeFromEmpty(jp, ctxt);
}
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
if (t != JsonToken.FIELD_NAME) {
if (t == JsonToken.END_OBJECT) {
throw ctxt.mappingException("Can not deserialize a Map.Entry out of empty JSON Object");
}
throw ctxt.mappingException(handledType(), t);
}
final KeyDeserializer keyDes = _keyDeserializer;
final JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
final String keyStr = jp.getCurrentName();
Object key = keyDes.deserializeKey(keyStr, ctxt);
Object value = null;
// And then the value...
t = jp.nextToken();
try {
// Note: must handle null explicitly here; value deserializers won't
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
} catch (Exception e) {
wrapAndThrow(e, Map.Entry.class, keyStr);
}
// Close, but also verify that we reached the END_OBJECT
t = jp.nextToken();
if (t != JsonToken.END_OBJECT) {
if (t == JsonToken.FIELD_NAME) { // most likely
throw ctxt.mappingException("Problem binding JSON into Map.Entry: more than one entry in JSON (second field: '"+jp.getCurrentName()+"')");
}
// how would this occur?
throw ctxt.mappingException("Problem binding JSON into Map.Entry: unexpected content after JSON Object entry: "+t);
}
return new AbstractMap.SimpleEntry<Object,Object>(key, value);
}
@Override
public Map.Entry
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> /**
* Method for constructing a marker type that indicates missing generic
* type information, which is handled same as simple type for
* <code>java.lang.Object</code>.
*/
public static JavaType unknownType() {
return defaultInstance()._unknownType();
}
/**
* Static helper method that can be called to figure out type-erased
* call for given JDK type. It can be called statically since type resolution
* process can never change actual type-erased class; thereby static
* default instance is used for determination.
*/
public static Class<?> rawClass(Type t) {
if (t instanceof Class<?>) {
return (Class<?>) t;
}
// Shouldbe able to optimize bit more in future...
return defaultInstance().constructType(t).getRawClass();
}
/*
/**********************************************************
/* Type conversion, parameterization resolution methods
/**********************************************************
*/
/**
* Factory method for creating a subtype of given base type, as defined
* by specified subclass; but retaining generic type information if any.
* Can be used, for example, to get equivalent of "HashMap<String,Integer>"
* from "Map<String,Integer>" by giving <code>HashMap.class</code>
* as subclass.
*/
public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
{
// simple optimization to avoid costly introspection if type-erased type does NOT differ
if (baseType.getRawClass() == subclass) {
return baseType;
}
// Currently only SimpleType instances can become something else
if (baseType instanceof SimpleType) {
// and only if subclass is an array, Collection or Map
if (subclass.isArray()
|| Map.class.isAssignableFrom(subclass)
|| Collection.class.isAssignableFrom(subclass)) {
// need to assert type compatibility...
if (!baseType.getRawClass().isAssignableFrom(subclass)) {
throw new IllegalArgumentException("Class "+subclass.getClass().getName()+" not subtype of "+baseType);
}
// this _should_ work, right?
JavaType subtype = _fromClass(subclass, new TypeBindings(this, baseType.getRawClass()));
// one more thing: handlers to copy?
Object h = baseType.getValueHandler();
if (h != null) {
subtype = subtype.withValueHandler(h);
}
h = baseType.getTypeHandler();
if (h != null) {
subtype = subtype.withTypeHandler(h);
}
return subtype;
}
}
// otherwise regular narrowing should work just fine
return baseType.narrowBy(subclass);
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
if (target == List.class) {
return _arrayListSuperInterfaceChain(current);
}
}
return _doFindSuperInterfaceChain(current, target);
}
protected HierarchicType _doFindSuperInterfaceChain(HierarchicType current, Class<?> target)
{
Class<?> raw = current.getRawClass();
Type[] parents = raw.getGenericInterfaces();
// as long as there are superclasses
// and unless we have already seen the type (<T extends X<T>>)
if (parents != null) {
for (Type parent : parents) {
HierarchicType sup = _findSuperInterfaceChain(parent, target);
if (sup != null) {
sup.setSubType(current);
current.setSuperType(sup);
return current;
}
}
}
// and then super-class if any
Type parent = raw.getGenericSuperclass();
if (parent != null) {
HierarchicType sup = _findSuperInterfaceChain(parent, target);
if (sup != null) {
sup.setSubType(current);
current.setSuperType(sup);
return current;
}
}
return null;
}
protected synchronized HierarchicType _hashMapSuperInterfaceChain(HierarchicType current)
{
if (_cachedHashMapType == null) {
HierarchicType base = current.deepCloneWithoutSubtype();
_doFindSuperInterfaceChain(base, Map.class);
_cachedHashMapType = base.getSuperType();
}
HierarchicType t = _cachedHashMapType.deepCloneWithoutSubtype();
current.setSuperType(t);
t.setSubType(current);
return current;
}
protected synchronized HierarchicType _arrayListSuperInterfaceChain(HierarchicType current)
{
if (_cachedArrayListType == null) {
HierarchicType base = current.deepCloneWithoutSubtype();
_doFindSuperInterfaceChain(base, List.class);
_cachedArrayListType = base.getSuperType();
}
HierarchicType t = _cachedArrayListType.deepCloneWithoutSubtype();
current.setSuperType(t);
t.setSubType(current);
return current;
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> throws IOException, JsonProcessingException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
throw ctxt.mappingException(EnumSet.class);
}
EnumSet result = constructSet();
JsonToken t;
try {
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
/* What to do with nulls? Fail or ignore? Fail, for now
* (note: would fail if we passed it to EnumDeserializer, too,
* but in general nulls should never be passed to non-container
* deserializers)
*/
if (t == JsonToken.VALUE_NULL) {
throw ctxt.mappingException(_enumClass);
}
Enum<?> value = _enumDeserializer.deserialize(jp, ctxt);
/* 24-Mar-2012, tatu: As per [JACKSON-810], may actually get nulls;
* but EnumSets don't allow nulls so need to skip.
*/
if (value != null) {
result.add(value);
}
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
@SuppressWarnings("unchecked")
private EnumSet constructSet()
{
// superbly ugly... but apparently necessary
return EnumSet.noneOf(_enumClass);
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> return it; otherwise returns null.
*/
protected JsonSerializer<Object> _findContentSerializer(SerializerProvider prov,
Annotated a)
throws JsonMappingException
{
AnnotationIntrospector intr = prov.getAnnotationIntrospector();
Object serDef = intr.findContentSerializer(a);
if (serDef != null) {
return prov.serializerInstance(a, serDef);
}
return null;
}
/**
* Method called to find filter that is configured to be used with bean
* serializer being built, if any.
*/
protected Object findFilterId(SerializationConfig config, BeanDescription beanDesc) {
return config.getAnnotationIntrospector().findFilterId((Annotated)beanDesc.getClassInfo());
}
/**
* Helper method to check whether global settings and/or class
* annotations for the bean class indicate that static typing
* (declared types) should be used for properties.
* (instead of dynamic runtime types).
*
* @since 2.1 (earlier had variant with additional 'property' parameter)
*/
protected boolean usesStaticTyping(SerializationConfig config,
BeanDescription beanDesc, TypeSerializer typeSer)
{
/* 16-Aug-2010, tatu: If there is a (value) type serializer, we can not force
* static typing; that would make it impossible to handle expected subtypes
*/
if (typeSer != null) {
return false;
}
AnnotationIntrospector intr = config.getAnnotationIntrospector();
JsonSerialize.Typing t = intr.findSerializationTyping(beanDesc.getClassInfo());
if (t != null && t != JsonSerialize.Typing.DEFAULT_TYPING) {
return (t == JsonSerialize.Typing.STATIC);
}
return config.isEnabled(MapperFeature.USE_STATIC_TYPING);
}
protected Class<?> _verifyAsClass(Object src, String methodName, Class<?> noneClass)
{
if (src == null) {
return null;
}
if (!(src instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector."+methodName+"() returned value of type "+src.getClass().getName()+": expected type JsonSerializer or Class<JsonSerializer> instead");
}
Class<?> cls = (Class<?>) src;
if (cls == noneClass || ClassUtil.isBogusClass(cls)) {
return null;
}
return cls;
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> already had explicitly annotated, leave as-is
// but skip, if new one not annotated
if (!explicit) {
return;
}
// both explicit: verify
verify = true;
} else {
// otherwise only verify if neither explicitly annotated.
verify = !explicit;
}
// one more thing: ok to override in sub-class
if (verify && (oldOne.getClass() == newOne.getClass())) {
// [databind#667]: avoid one particular class of bogus problems
Class<?> oldType = oldOne.getRawParameterType(0);
Class<?> newType = newOne.getRawParameterType(0);
if (oldType == newType) {
throw new IllegalArgumentException("Conflicting "+TYPE_DESCS[typeIndex]
+" creators: already had explicitly marked "+oldOne+", encountered "+newOne);
}
// otherwise, which one to choose?
if (newType.isAssignableFrom(oldType)) {
// new type more generic, use old
return;
}
// new type more specific, use it
}
}
if (explicit) {
_explicitCreators |= mask;
}
_creators[typeIndex] = _fixAccess(newOne);
}
/*
/**********************************************************
/* Helper class(es)
/**********************************************************
*/
protected final static class Vanilla
extends ValueInstantiator
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
public final static int TYPE_COLLECTION = 1;
public final static int TYPE_MAP = 2;
public final static int TYPE_HASH_MAP = 3;
private final int _type;
public Vanilla(int t) {
_type = t;
}
@Override
public String getValueTypeDesc() {
switch (_type) {
case TYPE_COLLECTION: return ArrayList.class.getName();
case TYPE_MAP: return LinkedHashMap.class.getName();
case TYPE_HASH_MAP: return HashMap.class.getName();
}
return Object.class.getName();
}
@Override
public boolean canInstantiate() { return true; }
@Override
public boolean canCreateUsingDefault() { return true; }
@Override
public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
switch (_type) {
case TYPE_COLLECTION: return new ArrayList<Object>();
case TYPE_MAP: return new LinkedHashMap<String,Object>();
case TYPE_HASH_MAP: return new HashMap<String,Object>();
}
throw new IllegalStateException("Unknown type "+_type);
}
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> annotation ("+cc.getName()+"): "+iae.getMessage(), null, iae);
}
}
// ... as well as deserializer for contents:
JavaType contentType = type.getContentType();
if (contentType.getValueHandler() == null) { // as with above, avoid resetting (which would trigger exception)
Object cdDef = intr.findContentDeserializer(a);
if (cdDef != null) {
JsonDeserializer<?> cd = null;
if (cdDef instanceof JsonDeserializer<?>) {
cdDef = (JsonDeserializer<?>) cdDef;
} else {
Class<?> cdClass = _verifyAsClass(cdDef, "findContentDeserializer", JsonDeserializer.None.class);
if (cdClass != null) {
cd = ctxt.deserializerInstance(a, cdClass);
}
}
if (cd != null) {
type = type.withContentValueHandler(cd);
}
}
}
}
return type;
}
/*
/**********************************************************
/* Helper methods, other
/**********************************************************
*/
/**
* Helper method used to prevent both caching and cache lookups for structured
* types that have custom value handlers
*
* @since 2.4.6
*/
private boolean _hasCustomValueHandler(JavaType t) {
if (t.isContainerType()) {
JavaType ct = t.getContentType();
if (ct != null) {
return (ct.getValueHandler() != null) || (ct.getTypeHandler() != null);
}
}
return false;
}
private Class<?> _verifyAsClass(Object src, String methodName, Class<?> noneClass)
{
if (src == null) {
return null;
}
if (!(src instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector."+methodName+"() returned value of type "+src.getClass().getName()+": expected type JsonSerializer or Class<JsonSerializer> instead");
}
Class<?> cls = (Class<?>) src;
if (cls == noneClass || ClassUtil.isBogusClass(cls)) {
return null;
}
return cls;
}
/*
/**********************************************************
/* Overridable error reporting methods
/**********************************************************
*/
protected JsonDeserializer<Object> _handleUnknownValueDeserializer(JavaType type)
throws JsonMappingException
{
/* Let's try to figure out the reason, to give better error
* messages
*/
Class<?> rawClass = type.getRawClass();
if (!ClassUtil.isConcrete(rawClass)) {
throw new JsonMappingException("Can not find a Value deserializer for abstract type "+type);
}
throw new
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> or calling application. Determination is done using
* {@link JacksonStdImpl} annotation on deserializer class.
*/
protected boolean isDefaultDeserializer(JsonDeserializer<?> deserializer) {
return ClassUtil.isJacksonStdImpl(deserializer);
}
protected boolean isDefaultKeyDeserializer(KeyDeserializer keyDeser) {
return ClassUtil.isJacksonStdImpl(keyDeser);
}
/*
/**********************************************************
/* Partial JsonDeserializer implementation
/**********************************************************
*/
/**
* Base implementation that does not assume specific type
* inclusion mechanism. Sub-classes are expected to override
* this method if they are to handle type information.
*/
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
}
/*
/**********************************************************
/* Helper methods for sub-classes, parsing: while mostly
/* useful for numeric types, can be also useful for dealing
/* with things serialized as numbers (such as Dates).
/**********************************************************
*/
protected final boolean _parseBooleanPrimitive(JsonParser jp, DeserializationContext ctxt) throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_TRUE) return true;
if (t == JsonToken.VALUE_FALSE) return false;
if (t == JsonToken.VALUE_NULL) return false;
// [JACKSON-78]: should accept ints too, (0 == false, otherwise true)
if (t == JsonToken.VALUE_NUMBER_INT) {
// 11-Jan-2012, tatus: May be outside of int...
if (jp.getNumberType() == NumberType.INT) {
return (jp.getIntValue() != 0);
}
return _parseBooleanFromNumber(jp, ctxt);
}
// And finally, let's allow Strings to be converted too
if (t == JsonToken.VALUE_STRING) {
String text = jp.getText().trim();
// [#422]: Allow aliases
if ("true".equals(text) || "True".equals(text)) {
return true;
}
if ("false".equals(text) || "False".equals(text) || text.length() == 0) {
return false;
}
if (_hasTextualNull(text)) {
return false;
}
throw ctxt.weirdStringException(text, _valueClass, "only \"true\" or \"false\" recognized");
}
// [databind#381]
if (t == JsonToken.START_
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final boolean parsed = _parseBooleanPrimitive(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'boolean' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final Boolean _parseBoolean(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_TRUE) {
return Boolean.TRUE;
}
if (t == JsonToken.VALUE_FALSE) {
return Boolean.FALSE;
}
// [JACKSON-78]: should accept ints too, (0 == false, otherwise true)
if (t == JsonToken.VALUE_NUMBER_INT) {
// 11-Jan-2012, tatus: May be outside of int...
if (jp.getNumberType() == NumberType.INT) {
return (jp.getIntValue() == 0) ? Boolean.FALSE : Boolean.TRUE;
}
return Boolean.valueOf(_parseBooleanFromNumber(jp, ctxt));
}
if (t == JsonToken.VALUE_NULL) {
return (Boolean) getNullValue();
}
// And finally, let's allow Strings to be converted too
if (t == JsonToken.VALUE_STRING) {
String text = jp.getText().trim();
// [#422]: Allow aliases
if ("true".equals(text) || "True".equals(text)) {
return Boolean.TRUE;
}
if ("false".equals(text) || "False".equals(text)) {
return Boolean.FALSE;
}
if (text.length() == 0) {
return (Boolean) getEmptyValue();
}
if (_hasTextualNull(text)) {
return (Boolean) getNullValue();
}
throw ctxt.weirdStringException(text, _valueClass, "only \"true\" or \"false\" recognized");
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Boolean parsed = _parseBoolean(jp, ctxt);
t = jp.nextToken();
if (t != Json
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Token.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Boolean' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final boolean _parseBooleanFromNumber(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
if (jp.getNumberType() == NumberType.LONG) {
return (jp.getLongValue() == 0L) ? Boolean.FALSE : Boolean.TRUE;
}
// no really good logic; let's actually resort to textual comparison
String str = jp.getText();
if ("0.0".equals(str) || "0".equals(str)) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
protected Byte _parseByte(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return jp.getByteValue();
}
if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse
String text = jp.getText().trim();
if (_hasTextualNull(text)) {
return (Byte) getNullValue();
}
int value;
try {
int len = text.length();
if (len == 0) {
return (Byte) getEmptyValue();
}
value = NumberInput.parseInt(text);
} catch (IllegalArgumentException iae) {
throw ctxt.weirdStringException(text, _valueClass, "not a valid Byte value");
}
// So far so good: but does it fit?
// as per [JACKSON-804], allow range up to 255, inclusive
if (value < Byte.MIN_VALUE || value > 255) {
throw ctxt.weirdStringException(text, _valueClass, "overflow, value can not be represented as 8-bit value");
}
return Byte.valueOf((byte) value);
}
if (t == JsonToken.VALUE_NULL) {
return (Byte) getNullValue();
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Byte parsed = _parseByte(jp, ctxt
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
}
return parsed;
}
throw ctxt.mappingException(_valueClass, t);
}
protected Short _parseShort(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return jp.getShortValue();
}
if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse
String text = jp.getText().trim();
int value;
try {
int len = text.length();
if (len == 0) {
return (Short) getEmptyValue();
}
if (_hasTextualNull(text)) {
return (Short) getNullValue();
}
value = NumberInput.parseInt(text);
} catch (IllegalArgumentException iae) {
throw ctxt.weirdStringException(text, _valueClass, "not a valid Short value");
}
// So far so good: but does it fit?
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
throw ctxt.weirdStringException(text, _valueClass, "overflow, value can not be represented as 16-bit value");
}
return Short.valueOf((short) value);
}
if (t == JsonToken.VALUE_NULL) {
return (Short) getNullValue();
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Short parsed = _parseShort(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Short' value but there was more than a single value in the array");
}
return parsed;
}
throw ctxt.mappingException(_valueClass, t);
}
protected final short _parseShortPrimitive(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
int value = _parseIntPrimitive(jp, ctxt);
// So far so good: but does it fit?
if
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
throw ctxt.weirdStringException(String.valueOf(value),
_valueClass, "overflow, value can not be represented as 16-bit value");
}
return (short) value;
}
protected final int _parseIntPrimitive(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
// Int works as is, coercing fine as well
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return jp.getIntValue();
}
if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse
String text = jp.getText().trim();
if (_hasTextualNull(text)) {
return 0;
}
try {
int len = text.length();
if (len > 9) {
long l = Long.parseLong(text);
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
throw ctxt.weirdStringException(text, _valueClass,
"Overflow: numeric value ("+text+") out of range of int ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")");
}
return (int) l;
}
if (len == 0) {
return 0;
}
return NumberInput.parseInt(text);
} catch (IllegalArgumentException iae) {
throw ctxt.weirdStringException(text, _valueClass, "not a valid int value");
}
}
if (t == JsonToken.VALUE_NULL) {
return 0;
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final int parsed = _parseIntPrimitive(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'int' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final Integer _parseInteger(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return Integer.valueOf(jp.getIntValue());
}
if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse
String text = jp.getText().trim();
try {
int len = text.length();
if (_hasTextualNull(text)) {
return (Integer) getNullValue();
}
if (len > 9) {
long l = Long.parseLong(text);
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
throw ctxt.weirdStringException(text, _valueClass,
"Overflow: numeric value ("+text+") out of range of Integer ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")");
}
return Integer.valueOf((int) l);
}
if (len == 0) {
return (Integer) getEmptyValue();
}
return Integer.valueOf(NumberInput.parseInt(text));
} catch (IllegalArgumentException iae) {
throw ctxt.weirdStringException(text, _valueClass, "not a valid Integer value");
}
}
if (t == JsonToken.VALUE_NULL) {
return (Integer) getNullValue();
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Integer parsed = _parseInteger(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Integer' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final Long _parseLong(JsonParser jp, DeserializationContext ctxt) throws IOException
{
JsonToken t = jp.getCurrentToken();
// it should be ok to coerce (although may fail, too)
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) {
return jp.getLongValue();
}
// let's allow Strings to be converted too
if (t == JsonToken.VALUE_STRING) {
// !!! 05-Jan-2009, tatu: Should we try to limit value space, JDK is too lenient?
String text = jp.
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>getText().trim();
if (text.length() == 0) {
return (Long) getEmptyValue();
}
if (_hasTextualNull(text)) {
return (Long) getNullValue();
}
try {
return Long.valueOf(NumberInput.parseLong(text));
} catch (IllegalArgumentException iae) { }
throw ctxt.weirdStringException(text, _valueClass, "not a valid Long value");
}
if (t == JsonToken.VALUE_NULL) {
return (Long) getNullValue();
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Long parsed = _parseLong(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Long' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final long _parseLongPrimitive(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) {
return jp.getLongValue();
}
if (t == JsonToken.VALUE_STRING) {
String text = jp.getText().trim();
if (text.length() == 0 || _hasTextualNull(text)) {
return 0L;
}
try {
return NumberInput.parseLong(text);
} catch (IllegalArgumentException iae) { }
throw ctxt.weirdStringException(text, _valueClass, "not a valid long value");
}
if (t == JsonToken.VALUE_NULL) {
return 0L;
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final long parsed = _parseLongPrimitive(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'long' value but there was more than a single value in the array");
}
return
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> parsed;
}
throw ctxt.mappingException(_valueClass, t);
}
protected final Float _parseFloat(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
// We accept couple of different types; obvious ones first:
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return jp.getFloatValue();
}
// And finally, let's allow Strings to be converted too
if (t == JsonToken.VALUE_STRING) {
String text = jp.getText().trim();
if (text.length() == 0) {
return (Float) getEmptyValue();
}
if (_hasTextualNull(text)) {
return (Float) getNullValue();
}
switch (text.charAt(0)) {
case 'I':
if (_isPosInf(text)) {
return Float.POSITIVE_INFINITY;
}
break;
case 'N':
if (_isNaN(text)) {
return Float.NaN;
}
break;
case '-':
if (_isNegInf(text)) {
return Float.NEGATIVE_INFINITY;
}
break;
}
try {
return Float.parseFloat(text);
} catch (IllegalArgumentException iae) { }
throw ctxt.weirdStringException(text, _valueClass, "not a valid Float value");
}
if (t == JsonToken.VALUE_NULL) {
return (Float) getNullValue();
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Float parsed = _parseFloat(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final float _parseFloatPrimitive(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return jp.getFloatValue();
}
if (t == JsonToken.VALUE_STRING) {
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> String text = jp.getText().trim();
if (text.length() == 0 || _hasTextualNull(text)) {
return 0.0f;
}
switch (text.charAt(0)) {
case 'I':
if (_isPosInf(text)) {
return Float.POSITIVE_INFINITY;
}
break;
case 'N':
if (_isNaN(text)) { return Float.NaN; }
break;
case '-':
if (_isNegInf(text)) {
return Float.NEGATIVE_INFINITY;
}
break;
}
try {
return Float.parseFloat(text);
} catch (IllegalArgumentException iae) { }
throw ctxt.weirdStringException(text, _valueClass, "not a valid float value");
}
if (t == JsonToken.VALUE_NULL) {
return 0.0f;
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final float parsed = _parseFloatPrimitive(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'float' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final Double _parseDouble(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return jp.getDoubleValue();
}
if (t == JsonToken.VALUE_STRING) {
String text = jp.getText().trim();
if (text.length() == 0) {
return (Double) getEmptyValue();
}
if (_hasTextualNull(text)) {
return (Double) getNullValue();
}
switch (text.charAt(0)) {
case 'I':
if (_isPosInf(text)) {
return Double.POSITIVE_INFINITY;
}
break;
case 'N':
if (_isNaN(text)) {
return Double.NaN;
}
break;
case '-':
if (_isNegInf(text)) {
return Double.NEGATIVE_INFINITY;
}
break;
}
try {
return parse
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Double(text);
} catch (IllegalArgumentException iae) { }
throw ctxt.weirdStringException(text, _valueClass, "not a valid Double value");
}
if (t == JsonToken.VALUE_NULL) {
return (Double) getNullValue();
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Double parsed = _parseDouble(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Double' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected final double _parseDoublePrimitive(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
// We accept couple of different types; obvious ones first:
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
return jp.getDoubleValue();
}
// And finally, let's allow Strings to be converted too
if (t == JsonToken.VALUE_STRING) {
String text = jp.getText().trim();
if (text.length() == 0 || _hasTextualNull(text)) {
return 0.0;
}
switch (text.charAt(0)) {
case 'I':
if (_isPosInf(text)) {
return Double.POSITIVE_INFINITY;
}
break;
case 'N':
if (_isNaN(text)) {
return Double.NaN;
}
break;
case '-':
if (_isNegInf(text)) {
return Double.NEGATIVE_INFINITY;
}
break;
}
try {
return parseDouble(text);
} catch (IllegalArgumentException iae) { }
throw ctxt.weirdStringException(text, _valueClass, "not a valid double value");
}
if (t == JsonToken.VALUE_NULL) {
return 0.0;
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final double parsed = _parseDoublePrimitive(jp, ctxt);
t = jp.nextToken();
if
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
}
return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
protected java.util.Date _parseDate(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NUMBER_INT) {
return new java.util.Date(jp.getLongValue());
}
if (t == JsonToken.VALUE_NULL) {
return (java.util.Date) getNullValue();
}
if (t == JsonToken.VALUE_STRING) {
String value = null;
try {
// As per [JACKSON-203], take empty Strings to mean
value = jp.getText().trim();
if (value.length() == 0) {
return (Date) getEmptyValue();
}
if (_hasTextualNull(value)) {
return (java.util.Date) getNullValue();
}
return ctxt.parseDate(value);
} catch (IllegalArgumentException iae) {
throw ctxt.weirdStringException(value, _valueClass,
"not a valid representation (error: "+iae.getMessage()+")");
}
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Date parsed = _parseDate(jp, ctxt);
t = jp.nextToken();
if (t != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'java.util.Date' value but there was more than a single value in the array");
}
return parsed;
}
throw ctxt.mappingException(_valueClass, t);
}
/**
* Helper method for encapsulating calls to low-level double value parsing; single place
* just because we need a work-around that must be applied to all calls.
*/
protected final static double parseDouble(String numStr) throws NumberFormatException
{
// [JACKSON-486]: avoid some nasty float representations... but should it be MIN_NORMAL or MIN_VALUE?
// for now, MIN_VALUE, since MIN_NORMAL is JDK 1.6
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> if (NumberInput.NASTY_SMALL_DOUBLE.equals(numStr)) {
return Double.MIN_VALUE;
}
return Double.parseDouble(numStr);
}
/**
* Helper method used for accessing String value, if possible, doing
* necessary conversion or throwing exception as necessary.
*
* @since 2.1
*/
protected final String _parseString(JsonParser jp, DeserializationContext ctxt) throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_STRING) {
return jp.getText();
}
// Issue#381
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final String parsed = _parseString(jp, ctxt);
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'String' value but there was more than a single value in the array");
}
return parsed;
}
String value = jp.getValueAsString();
if (value != null) {
return value;
}
throw ctxt.mappingException(String.class, jp.getCurrentToken());
}
/**
* Helper method that may be used to support fallback for Empty String / Empty Array
* non-standard representations; usually for things serialized as JSON Objects.
*
* @since 2.5
*/
protected T _deserializeFromEmpty(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_ARRAY) {
if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
t = jp.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
throw ctxt.mappingException(handledType(), JsonToken.START_ARRAY);
}
} else if (t == JsonToken.VALUE_STRING) {
if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
String str = jp.getText().trim();
if (str.isEmpty()) {
return null;
}
}
}
throw ctxt.mappingException(handledType());
}
/**
* Helper method called to determine if we are seeing String value of
* "null", and, further, that it should be coerced to null just like
* null token.
*
* @since 2.3
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.deser.impl;
import java.io.IOException;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdResolver;
import com.fasterxml.jackson.annotation.SimpleObjectIdResolver;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
/**
* Object that knows how to deserialize Object Ids.
*/
public class ObjectIdReader
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
protected final JavaType _idType;
public final PropertyName propertyName;
/**
* Blueprint generator instance: actual instance will be
* fetched from {@link SerializerProvider} using this as
* the key.
*/
public final ObjectIdGenerator<?> generator;
public final ObjectIdResolver resolver;
/**
* Deserializer used for deserializing id values.
*/
protected final JsonDeserializer<Object> _deserializer;
public final SettableBeanProperty idProperty;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
@SuppressWarnings("unchecked")
protected ObjectIdReader(JavaType t, PropertyName propName, ObjectIdGenerator<?> gen,
JsonDeserializer<?> deser, SettableBeanProperty idProp, ObjectIdResolver resolver)
{
_idType = t;
propertyName = propName;
generator = gen;
this.resolver = resolver;
_deserializer = (JsonDeserializer<Object>) deser;
idProperty = idProp;
}
@Deprecated // since 2.4
protected ObjectIdReader(JavaType t, PropertyName propName, ObjectIdGenerator<?> gen,
JsonDeserializer<?> deser, SettableBeanProperty idProp)
{
this(t,propName, gen, deser, idProp, new SimpleObjectIdResolver());
}
/**
* Factory method called by {@link com.fasterxml.jackson.databind.ser.std.BeanSerializerBase}
* with the initial information based on standard settings for the type
* for which serializer is being built.
*/
public static ObjectIdReader construct(JavaType idType, PropertyName propName,
ObjectIdGenerator<?> generator, JsonDeserializer<?> deser,
SettableBeanProperty idProp, ObjectIdResolver resolver)
{
return new ObjectIdReader(idType, propName, generator, deser, idProp, resolver);
}
@Deprecated // since 2.4
public static ObjectIdReader construct(JavaType idType, PropertyName propName,
ObjectIdGenerator<?> generator, JsonDeserializer<?> deser,
SettableBeanProperty idProp)
{
return construct(id
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.util.ObjectBuffer;
/**
* Separate implementation for serializing String arrays (instead of
* using {@link ObjectArrayDeserializer}.
* Used if (and only if) no custom value deserializers are used.
*/
@JacksonStdImpl
public final class StringArrayDeserializer
extends StdDeserializer<String[]>
implements ContextualDeserializer
{
private static final long serialVersionUID = 1L;
public final static StringArrayDeserializer instance = new StringArrayDeserializer();
/**
* Value serializer to use, if not the standard one (which is inlined)
*/
protected JsonDeserializer<String> _elementDeserializer;
public StringArrayDeserializer() {
super(String[].class);
_elementDeserializer = null;
}
@SuppressWarnings("unchecked")
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
try {
while (true) {
String value = jp.nextTextValue();
if (value == null) {
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.END_ARRAY) {
break;
}
if (t != JsonToken.VALUE_NULL) {
value = _parseString(jp, ctxt);
}
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix);
}
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
try {
while (true) {
/* 30-Dec-2014, tatu: This may look odd, but let's actually call method
* that suggest we are expecting a String; this helps with some formats,
* notably XML. Note, however, that while we can get String, we can't
* assume that's what we use due to custom deserializer
*/
String value;
if (jp.nextTextValue() == null) {
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.END_ARRAY) {
break;
}
// Ok: no need to convert Strings, but must recognize nulls
value = (t == JsonToken.VALUE_NULL) ? deser.getNullValue() : deser.deserialize(jp, ctxt);
} else {
value = deser.deserialize(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
} catch (Exception e) {
// note: pass String.class, not String[].class, as we need element type for error info
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
private final String[] handleNonArray(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// [JACKSON-526]: implicit arrays from single values?
if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
// [JACKSON-620] Empty String can become null...
if ((jp.getCurrentToken() == JsonToken.VALUE_STRING)
&& ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
String str = jp
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> type resolution methods
/**********************************************************
*/
public JavaType resolveType(Class<?> cls) {
return _typeFactory._constructType(cls, this);
}
public JavaType resolveType(Type type) {
return _typeFactory._constructType(type, this);
}
/*
/**********************************************************
/* Accesors
/**********************************************************
*/
public int getBindingCount() {
if (_bindings == null) {
_resolve();
}
return _bindings.size();
}
@Deprecated // since 2.6, remove from 2.7
public JavaType findType(String name) {
return findType(name, true);
}
public JavaType findType(String name, boolean mustFind)
{
if (_bindings == null) {
_resolve();
}
JavaType t = _bindings.get(name);
if (t != null) {
return t;
}
if (_placeholders != null && _placeholders.contains(name)) {
return UNBOUND;
}
if (_parentBindings != null) {
return _parentBindings.findType(name);
}
// nothing found, so...
// Should we throw an exception or just return null?
/* [JACKSON-499] 18-Feb-2011, tatu: There are some tricky type bindings within
* java.util, such as HashMap$KeySet; so let's punt the problem
* (honestly not sure what to do -- they are unbound for good, I think)
*/
if (_contextClass != null) {
Class<?> enclosing = _contextClass.getEnclosingClass();
if (enclosing != null) {
// [JACKSON-572]: Actually, let's skip this for all non-static inner classes
// (which will also cover 'java.util' type cases...
if (!Modifier.isStatic(_contextClass.getModifiers())) {
return UNBOUND;
}
// ... so this piece of code should not be needed any more
/*
Package pkg = enclosing.getPackage();
if (pkg != null) {
// as per [JACKSON-533], also include "java.util.concurrent":
if (pkg.getName().startsWith("java.util")) {
return UNBOUND;
}
}
*/
}
}
if (!mustFind) {
return null;
}
String className;
if (_contextClass != null) {
className = _contextClass.getName();
} else if (_contextType != null) {
className = _contextType.toString();
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> else {
className = "UNKNOWN";
}
throw new IllegalArgumentException("Type variable '"+name
+"' can not be resolved (with context of class "+className+")");
//t = UNBOUND;
}
public void addBinding(String name, JavaType type)
{
// note: emptyMap() is unmodifiable, hence second check is needed:
if (_bindings == null || _bindings.size() == 0) {
_bindings = new LinkedHashMap<String,JavaType>();
}
_bindings.put(name, type);
}
public JavaType[] typesAsArray()
{
if (_bindings == null) {
_resolve();
}
if (_bindings.size() == 0) {
return NO_TYPES;
}
return _bindings.values().toArray(new JavaType[_bindings.size()]);
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected void _resolve()
{
_resolveBindings(_contextClass);
// finally: may have root level type info too
if (_contextType != null) {
int count = _contextType.containedTypeCount();
if (count > 0) {
for (int i = 0; i < count; ++i) {
String name = _contextType.containedTypeName(i);
JavaType type = _contextType.containedType(i);
addBinding(name, type);
}
}
}
// nothing bound? mark with empty map to prevent further calls
if (_bindings == null) {
_bindings = Collections.emptyMap();
}
}
public void _addPlaceholder(String name) {
if (_placeholders == null) {
_placeholders = new HashSet<String>();
}
_placeholders.add(name);
}
protected void _resolveBindings(Type t)
{
if (t == null) return;
Class<?> raw;
if (t instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) t;
Type[] args = pt.getActualTypeArguments();
if (args != null && args.length > 0) {
Class<?> rawType = (Class<?>) pt.getRawType();
TypeVariable<?>[] vars = rawType.getTypeParameters();
if (vars.length != args.length) {
throw new IllegalArgumentException("Strange parametrized type (in class "+rawType.getName()+"): number of type arguments != number of type parameters ("+args.length+" vs "+vars.length+")");
}
for (int i = 0, len = args.length; i < len; ++i) {
TypeVariable<?> var = vars[
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>i];
String name = var.getName();
if (_bindings == null) {
_bindings = new LinkedHashMap<String,JavaType>();
} else {
/* 24-Mar-2010, tatu: Better ensure that we do not overwrite something
* collected earlier (since we descend towards super-classes):
*/
if (_bindings.containsKey(name)) continue;
}
// first: add a placeholder to prevent infinite loops
_addPlaceholder(name);
// then resolve type
_bindings.put(name, _typeFactory._constructType(args[i], this));
}
}
raw = (Class<?>)pt.getRawType();
} else if (t instanceof Class<?>) {
raw = (Class<?>) t;
/* [JACKSON-677]: If this is an inner class then the generics are defined on the
* enclosing class so we have to check there as well. We don't
* need to call getEnclosingClass since anonymous classes declare
* generics
*/
Class<?> decl = raw.getDeclaringClass();
/* 08-Feb-2013, tatu: Except that if context is also super-class, we must
* skip it; context will be checked anyway, and we'd get StackOverflow if
* we went there.
*/
if (decl != null && !decl.isAssignableFrom(raw)) {
_resolveBindings(raw.getDeclaringClass());
}
/* 24-Mar-2010, tatu: Can not have true generics definitions, but can
* have lower bounds ("<T extends BeanBase>") in declaration itself
*/
TypeVariable<?>[] vars = raw.getTypeParameters();
if (vars != null && vars.length > 0) {
JavaType[] typeParams = null;
if (_contextType != null && raw.isAssignableFrom(_contextType.getRawClass())) {
typeParams = _typeFactory.findTypeParameters(_contextType, raw);
}
for (int i = 0; i < vars.length; i++) {
TypeVariable<?> var = vars[i];
String name = var.getName();
Type varType = var.getBounds()[0];
if (varType != null) {
if (_bindings == null) {
_bindings = new LinkedHashMap<String,JavaType>();
} else { // and no overwriting...
if (_bindings.containsKey(name)) continue;
}
_addPlaceholder(name); // to prevent infinite loops
if (typeParams != null && typeParams.length > i) {
_bindings.put(name, typeParams
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
}
final Collection<String> result = (Collection<String>) _valueInstantiator.createUsingDefault(ctxt);
return deserialize(jp, ctxt, result);
}
@Override
public Collection<String> deserialize(JsonParser jp, DeserializationContext ctxt,
Collection<String> result)
throws IOException
{
// Ok: must point to START_ARRAY
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt, result);
}
if (_valueDeserializer != null) {
return deserializeUsingCustom(jp, ctxt, result, _valueDeserializer);
}
try {
while (true) {
// First the common case:
String value = jp.nextTextValue();
if (value != null) {
result.add(value);
continue;
}
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.END_ARRAY) {
break;
}
if (t != JsonToken.VALUE_NULL) {
value = _parseString(jp, ctxt);
}
result.add(value);
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
return result;
}
private Collection<String> deserializeUsingCustom(JsonParser jp, DeserializationContext ctxt,
Collection<String> result, final JsonDeserializer<String> deser) throws IOException
{
while (true) {
/* 30-Dec-2014, tatu: This may look odd, but let's actually call method
* that suggest we are expecting a String; this helps with some formats,
* notably XML. Note, however, that while we can get String, we can't
* assume that's what we use due to custom deserializer
*/
String value;
if (jp.nextTextValue() == null) {
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.END_ARRAY) {
break;
}
// Ok: no need to convert Strings, but must recognize nulls
value = (t == JsonToken.VALUE_NULL) ? deser.getNullValue() : deser.deserialize(jp, ctxt);
} else {
value = deser.deserialize(jp, ctxt);
}
result.add(value);
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
/**
*
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> Helper method called when current token is not START_ARRAY. Will either
* throw an exception, or try to handle value as if member of implicit
* array, depending on configuration.
*/
private final Collection<String> handleNonArray(JsonParser jp, DeserializationContext ctxt, Collection<String> result) throws IOException
{
// [JACKSON-526]: implicit arrays from single values?
if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
throw ctxt.mappingException(_collectionType.getRawClass());
}
// Strings are one of "native" (intrinsic) types, so there's never type deserializer involved
JsonDeserializer<String> valueDes = _valueDeserializer;
JsonToken t = jp.getCurrentToken();
String value;
if (t == JsonToken.VALUE_NULL) {
value = (valueDes == null) ? null : valueDes.getNullValue();
} else {
value = (valueDes == null) ? _parseString(jp, ctxt) : valueDes.deserialize(jp, ctxt);
}
result.add(value);
return result;
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.ser.impl;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.SerializedString;
import com.fasterxml.jackson.databind.*;
/**
* Object that knows how to serialize Object Ids.
*/
public final class ObjectIdWriter
{
public final JavaType idType;
/**
* Name of id property to write, if not null: if null, should
* only write references, but id property is handled by some
* other entity.
*/
public final SerializableString propertyName;
/**
* Blueprint generator instance: actual instance will be
* fetched from {@link SerializerProvider} using this as
* the key.
*/
public final ObjectIdGenerator<?> generator;
/**
* Serializer used for serializing id values.
*/
public final JsonSerializer<Object> serializer;
/**
* Marker that indicates what the first reference is to be
* serialized as full POJO, or as Object Id (other references
* will always be serialized as Object Id)
*
* @since 2.1
*/
public final boolean alwaysAsId;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
@SuppressWarnings("unchecked")
protected ObjectIdWriter(JavaType t, SerializableString propName,
ObjectIdGenerator<?> gen, JsonSerializer<?> ser, boolean alwaysAsId)
{
idType = t;
propertyName = propName;
generator = gen;
serializer = (JsonSerializer<Object>) ser;
this.alwaysAsId = alwaysAsId;
}
/**
* Factory method called by {@link com.fasterxml.jackson.databind.ser.std.BeanSerializerBase}
* with the initial information based on standard settings for the type
* for which serializer is being built.
*
* @since 2.3
*/
public static ObjectIdWriter construct(JavaType idType, PropertyName propName,
ObjectIdGenerator<?> generator, boolean alwaysAsId)
{
String simpleName = (propName == null) ? null : propName.getSimpleName();
return construct(idType, simpleName, generator, alwaysAsId);
}
@Deprecated // since 2.3
public static ObjectIdWriter construct(JavaType idType, String propName,
ObjectIdGenerator<?> generator, boolean alwaysAsId)
{
SerializableString serName = (propName == null) ? null : new SerializedString(propName);
return new ObjectIdWriter(idType, serName, generator, null, alwaysAsId);
}
public ObjectIdWriter withSerializer(JsonSerializer<?> ser) {
return new
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>since 2.2
*/
public final boolean useStaticType() { return _asStatic; }
/*
/**********************************************************
/* Public API, type parameter access; pass-through
/**********************************************************
*/
@Override
public boolean hasGenericTypes() { return containedTypeCount() > 0; }
@Override
public JavaType getKeyType() { return null; }
@Override
public JavaType getContentType() { return null; }
@Override
public int containedTypeCount() { return 0; }
@Override
public JavaType containedType(int index) { return null; }
@Override
public String containedTypeName(int index) { return null; }
@Override
public abstract Class<?> getParameterSource();
/*
/**********************************************************
/* Extended API beyond ResolvedType
/**********************************************************
*/
// NOTE: not defined in Resolved type
/**
* Convenience method that is functionally same as:
*<code>
* JavaType t = containedType(index);
* if (t == null) {
* t = TypeFactory.unknownType();
* }
*</code>
* and typically used to eliminate need for null checks for common case
* where we just want to check if containedType is available first; and
* if not, use "unknown type" (which translates to <code>java.lang.Object</code>
* basically).
*
* @since 2.5
*/
public JavaType containedTypeOrUnknown(int index) {
JavaType t = containedType(index);
return (t == null) ? TypeFactory.unknownType() : t;
}
/*
/**********************************************************
/* Semi-public API, accessing handlers
/**********************************************************
*/
/**
* Method for accessing value handler associated with this type, if any
*/
@SuppressWarnings("unchecked")
public <T> T getValueHandler() { return (T) _valueHandler; }
/**
* Method for accessing type handler associated with this type, if any
*/
@SuppressWarnings("unchecked")
public <T> T getTypeHandler() { return (T) _typeHandler; }
/*
/**********************************************************
/* Support for producing signatures
/**********************************************************
*/
//public abstract String toCanonical();
/**
* Method for accessing signature that contains generic
* type information, in form compatible with JVM 1.5
* as per JLS. It is a superset of {@link #getErasedSignature},
* in that generic information can be automatically removed
* if necessary (just remove outermost
* angle brackets along with content inside)
*/
public String getGenericSignature() {
StringBuilder sb = new StringBuilder
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>>) _valueInstantiator.createFromString(ctxt, str);
}
}
return deserialize(jp, ctxt, null);
}
@Override
public Collection<Object> deserialize(JsonParser jp, DeserializationContext ctxt, Collection<Object> result0) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt, new ArrayBlockingQueue<Object>(1));
}
ArrayList<Object> tmp = new ArrayList<Object>();
JsonDeserializer<Object> valueDes = _valueDeserializer;
JsonToken t;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
try {
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
tmp.add(value);
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, tmp, tmp.size());
}
if (result0 != null) {
result0.addAll(tmp);
return result0;
}
return new ArrayBlockingQueue<Object>(tmp.size(), false, tmp);
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> long getLongValue() throws IOException, JsonParseException {
return currentNumericNode().longValue();
}
@Override
public int getIntValue() throws IOException, JsonParseException {
return currentNumericNode().intValue();
}
@Override
public Number getNumberValue() throws IOException, JsonParseException {
return currentNumericNode().numberValue();
}
@Override
public Object getEmbeddedObject()
{
if (!_closed) {
JsonNode n = currentNode();
if (n != null) {
if (n.isPojo()) {
return ((POJONode) n).getPojo();
}
if (n.isBinary()) {
return ((BinaryNode) n).binaryValue();
}
}
}
return null;
}
/*
/**********************************************************
/* Public API, typed binary (base64) access
/**********************************************************
*/
@Override
public byte[] getBinaryValue(Base64Variant b64variant)
throws IOException, JsonParseException
{
// Multiple possibilities...
JsonNode n = currentNode();
if (n != null) { // binary node?
byte[] data = n.binaryValue();
// (or TextNode, which can also convert automatically!)
if (data != null) {
return data;
}
// Or maybe byte[] as POJO?
if (n.isPojo()) {
Object ob = ((POJONode) n).getPojo();
if (ob instanceof byte[]) {
return (byte[]) ob;
}
}
}
// otherwise return null to mark we have no binary content
return null;
}
@Override
public int readBinaryValue(Base64Variant b64variant, OutputStream out)
throws IOException, JsonParseException
{
byte[] data = getBinaryValue(b64variant);
if (data != null) {
out.write(data, 0, data.length);
return data.length;
}
return 0;
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected JsonNode currentNode() {
if (_closed || _nodeCursor == null) {
return null;
}
return _nodeCursor.currentNode();
}
protected JsonNode currentNumericNode()
throws JsonParseException
{
JsonNode n = currentNode();
if (n == null || !n.isNumber()) {
JsonToken t = (n == null) ? null : n.asToken();
throw _constructError("Current token ("+t+") not numeric, can not use numeric value accessors");
}
return n;
}
@Override
protected void _handleEOF() throws JsonParseException {
_throwInternal();
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> }
}
serializer.serialize(elem, jgen, provider);
}
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
/* 05-Mar-2009, tatu: But one nasty edge is when we get
* StackOverflow: usually due to infinite loop. But that gets
* hidden within an InvocationTargetException...
*/
Throwable t = e;
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) {
throw (Error) t;
}
throw JsonMappingException.wrapWithPath(t, elem, i);
}
}
public void serializeContentsUsing(Object[] value, JsonGenerator jgen, SerializerProvider provider,
JsonSerializer<Object> ser) throws IOException
{
final int len = value.length;
final TypeSerializer typeSer = _valueTypeSerializer;
int i = 0;
Object elem = null;
try {
for (; i < len; ++i) {
elem = value[i];
if (elem == null) {
provider.defaultSerializeNull(jgen);
continue;
}
if (typeSer == null) {
ser.serialize(elem, jgen, provider);
} else {
ser.serializeWithType(elem, jgen, provider, typeSer);
}
}
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t = e;
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) {
throw (Error) t;
}
throw JsonMappingException.wrapWithPath(t, elem, i);
}
}
public void serializeTypedContents(Object[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
{
final int len = value.length;
final TypeSerializer typeSer = _valueTypeSerializer;
int i = 0;
Object elem = null;
try {
PropertySerializerMap serializers = _dynamicSerializers;
for (; i < len; ++i) {
elem = value[i];
if (elem == null) {
provider.defaultSerializeNull(jgen);
continue;
}
Class<?> cc = elem.getClass();
JsonSerializer<Object> serializer = serializers.serializerFor(cc);
if (serializer == null) {
serializer = _findAndAddDynamic(serializers, cc, provider);
}
serializer.
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>serializeWithType(elem, jgen, provider, typeSer);
}
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t = e;
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) {
throw (Error) t;
}
throw JsonMappingException.wrapWithPath(t, elem, i);
}
}
@SuppressWarnings("deprecation")
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
ObjectNode o = createSchemaNode("array", true);
if (typeHint != null) {
JavaType javaType = provider.constructType(typeHint);
if (javaType.isArrayType()) {
Class<?> componentType = ((ArrayType) javaType).getContentType().getRawClass();
// 15-Oct-2010, tatu: We can't serialize plain Object.class; but what should it produce here? Untyped?
if (componentType == Object.class) {
o.put("items", com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode());
} else {
JsonSerializer<Object> ser = provider.findValueSerializer(componentType, _property);
JsonNode schemaNode = (ser instanceof SchemaAware) ?
((SchemaAware) ser).getSchema(provider, null) :
com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
o.put("items", schemaNode);
}
}
}
return o;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonArrayFormatVisitor arrayVisitor = visitor.expectArrayFormat(typeHint);
if (arrayVisitor != null) {
TypeFactory tf = visitor.getProvider().getTypeFactory();
JavaType contentType = tf.moreSpecificType(_elementType, typeHint.getContentType());
if (contentType == null) {
throw new JsonMappingException("Could not resolve type");
}
JsonSerializer<?> valueSer = _elementSerializer;
if (valueSer == null) {
valueSer = visitor.getProvider().findValueSerializer(contentType, _property);
}
arrayVisitor.itemsFormat(valueSer, contentType);
}
}
protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
Class<?> type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider,
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
public class StackTraceElementDeserializer
extends StdScalarDeserializer<StackTraceElement>
{
private static final long serialVersionUID = 1L;
public StackTraceElementDeserializer() { super(StackTraceElement.class); }
@Override
public StackTraceElement deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
JsonToken t = jp.getCurrentToken();
// Must get an Object
if (t == JsonToken.START_OBJECT) {
String className = "", methodName = "", fileName = "";
int lineNumber = -1;
while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
String propName = jp.getCurrentName();
if ("className".equals(propName)) {
className = jp.getText();
} else if ("fileName".equals(propName)) {
fileName = jp.getText();
} else if ("lineNumber".equals(propName)) {
if (t.isNumeric()) {
lineNumber = jp.getIntValue();
} else {
throw JsonMappingException.from(jp, "Non-numeric token ("+t+") for property 'lineNumber'");
}
} else if ("methodName".equals(propName)) {
methodName = jp.getText();
} else if ("nativeMethod".equals(propName)) {
// no setter, not passed via constructor: ignore
} else {
handleUnknownProperty(jp, ctxt, _valueClass, propName);
}
}
return new StackTraceElement(className, methodName, fileName, lineNumber);
} else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final StackTraceElement value = deserialize(jp, ctxt);
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'java.lang.StackTraceElement' value but there was more than a single value in the array"
);
}
return value;
}
throw ctxt.mappingException(_valueClass, t);
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.jsontype.impl;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.jsontype.NamedType;
public class TypeNameIdResolver extends TypeIdResolverBase
{
protected final MapperConfig<?> _config;
/**
* Mappings from class name to type id, used for serialization
*/
protected final HashMap<String, String> _typeToId;
/**
* Mappings from type id to JavaType, used for deserialization
*/
protected final HashMap<String, JavaType> _idToType;
protected TypeNameIdResolver(MapperConfig<?> config, JavaType baseType,
HashMap<String, String> typeToId, HashMap<String, JavaType> idToType)
{
super(baseType, config.getTypeFactory());
_config = config;
_typeToId = typeToId;
_idToType = idToType;
}
public static TypeNameIdResolver construct(MapperConfig<?> config, JavaType baseType,
Collection<NamedType> subtypes, boolean forSer, boolean forDeser)
{
// sanity check
if (forSer == forDeser) throw new IllegalArgumentException();
HashMap<String, String> typeToId = null;
HashMap<String, JavaType> idToType = null;
if (forSer) {
typeToId = new HashMap<String, String>();
}
if (forDeser) {
idToType = new HashMap<String, JavaType>();
}
if (subtypes != null) {
for (NamedType t : subtypes) {
/* no name? Need to figure out default; for now, let's just
* use non-qualified class name
*/
Class<?> cls = t.getType();
String id = t.hasName() ? t.getName() : _defaultTypeId(cls);
if (forSer) {
typeToId.put(cls.getName(), id);
}
if (forDeser) {
/* 24-Feb-2011, tatu: [JACKSON-498] One more problem; sometimes
* we have same name for multiple types; if so, use most specific
* one.
*/
JavaType prev = idToType.get(id);
if (prev !=
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> (jp.getCurrentToken()) {
case FIELD_NAME:
case START_OBJECT:
if (_mapDeserializer != null) {
return _mapDeserializer.deserialize(jp, ctxt);
}
return mapObject(jp, ctxt);
case START_ARRAY:
if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
return mapArrayToArray(jp, ctxt);
}
if (_listDeserializer != null) {
return _listDeserializer.deserialize(jp, ctxt);
}
return mapArray(jp, ctxt);
case VALUE_EMBEDDED_OBJECT:
return jp.getEmbeddedObject();
case VALUE_STRING:
if (_stringDeserializer != null) {
return _stringDeserializer.deserialize(jp, ctxt);
}
return jp.getText();
case VALUE_NUMBER_INT:
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(jp, ctxt);
}
/* [JACKSON-100]: caller may want to get all integral values
* returned as BigInteger, for consistency
*/
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
return jp.getBigIntegerValue(); // should be optimal, whatever it is
}
return jp.getNumberValue(); // should be optimal, whatever it is
case VALUE_NUMBER_FLOAT:
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(jp, ctxt);
}
/* [JACKSON-72]: need to allow overriding the behavior regarding
* which type to use
*/
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
return jp.getDecimalValue();
}
return Double.valueOf(jp.getDoubleValue());
case VALUE_TRUE:
return Boolean.TRUE;
case VALUE_FALSE:
return Boolean.FALSE;
case VALUE_NULL: // should not get this but...
return null;
case END_ARRAY: // invalid
case END_OBJECT: // invalid
default:
throw ctxt.mappingException(Object.class);
}
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException
{
JsonToken t = jp.getCurrentToken();
switch (t) {
// First: does it look like we had type id wrapping of some kind?
case START_ARRAY:
case START_OBJECT:
case FIELD_NAME:
/* Output can be as JSON Object, Array or scalar: no way to know
* a this point:
*/
return typeDeserializer.deserializeTypedFromAny(jp, ctxt
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>);
return l;
}
ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] values = buffer.resetAndStart();
int ptr = 0;
values[ptr++] = value;
values[ptr++] = value2;
int totalSize = ptr;
do {
value = deserialize(jp, ctxt);
++totalSize;
if (ptr >= values.length) {
values = buffer.appendCompletedChunk(values);
ptr = 0;
}
values[ptr++] = value;
} while (jp.nextToken() != JsonToken.END_ARRAY);
// let's create full array then
ArrayList<Object> result = new ArrayList<Object>(totalSize);
buffer.completeAndClearBuffer(values, ptr, result);
return result;
}
/**
* Method called to map a JSON Object into a Java value.
*/
protected Object mapObject(JsonParser jp, DeserializationContext ctxt) throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
// minor optimization; let's handle 1 and 2 entry cases separately
if (t == JsonToken.END_OBJECT) { // and empty one too
// empty map might work; but caller may want to modify... so better just give small modifiable
return new LinkedHashMap<String,Object>(2);
}
String field1 = jp.getCurrentName();
jp.nextToken();
Object value1 = deserialize(jp, ctxt);
if (jp.nextToken() == JsonToken.END_OBJECT) { // single entry; but we want modifiable
LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>(2);
result.put(field1, value1);
return result;
}
String field2 = jp.getCurrentName();
jp.nextToken();
Object value2 = deserialize(jp, ctxt);
if (jp.nextToken() == JsonToken.END_OBJECT) {
LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>(4);
result.put(field1, value1);
result.put(field2, value2);
return result;
}
// And then the general case; default map size is 16
LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>();
result.put(field1, value1);
result.put(field2, value2);
do {
String fieldName = jp.getCurrentName();
jp.nextToken();
result.put(fieldName, deserialize(jp, ctxt));
} while (jp.nextToken() != JsonToken.END_OBJECT);
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
return result;
}
/**
* Method called to map a JSON Array into a Java Object array (Object[]).
*/
protected Object[] mapArrayToArray(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Minor optimization to handle small lists (default size for ArrayList is 10)
if (jp.nextToken() == JsonToken.END_ARRAY) {
return NO_OBJECTS;
}
ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] values = buffer.resetAndStart();
int ptr = 0;
do {
Object value = deserialize(jp, ctxt);
if (ptr >= values.length) {
values = buffer.appendCompletedChunk(values);
ptr = 0;
}
values[ptr++] = value;
} while (jp.nextToken() != JsonToken.END_ARRAY);
return buffer.completeAndClearBuffer(values, ptr);
}
/*
/**********************************************************
/* Separate "vanilla" implementation for common case of
/* no custom deserializer overrides
/**********************************************************
*/
@JacksonStdImpl
public static class Vanilla
extends StdDeserializer<Object>
{
private static final long serialVersionUID = 1L;
public final static Vanilla std = new Vanilla();
public Vanilla() { super(Object.class); }
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
switch (jp.getCurrentTokenId()) {
case JsonTokenId.ID_START_OBJECT:
{
JsonToken t = jp.nextToken();
if (t == JsonToken.END_OBJECT) {
return new LinkedHashMap<String,Object>(2);
}
}
case JsonTokenId.ID_FIELD_NAME:
return mapObject(jp, ctxt);
case JsonTokenId.ID_START_ARRAY:
{
JsonToken t = jp.nextToken();
if (t == JsonToken.END_ARRAY) { // and empty one too
if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
return NO_OBJECTS;
}
return new ArrayList<Object>(2);
}
}
if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
return mapArrayToArray(jp, ctxt);
}
return mapArray(jp, ctxt);
case JsonTokenId.ID_EMBEDDED_OBJECT:
return jp.getEmbeddedObject();
case JsonTokenId.ID_STRING:
return jp.getText();
case JsonTokenId.ID_NUMBER_INT:
if (ctxt.isEnabled(DeserializationFeature
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
return;
}
JsonSerializer<Object> ser = _serializer;
if (ser == null) {
Class<?> cls = value.getClass();
PropertySerializerMap map = _dynamicSerializers;
ser = map.serializerFor(cls);
if (ser == null) {
ser = _findAndAddDynamic(map, cls, prov);
}
}
if (_suppressableValue != null) {
if (MARKER_FOR_EMPTY == _suppressableValue) {
if (ser.isEmpty(prov, value)) {
return;
}
} else if (_suppressableValue.equals(value)) {
return;
}
}
// For non-nulls, first: simple check for direct cycles
if (value == bean) {
if (_handleSelfReference(bean, jgen, prov, ser)) {
return;
}
}
// note: must verify we are using unwrapping serializer; if not, will write field name
if (!ser.isUnwrappingSerializer()) {
jgen.writeFieldName(_name);
}
if (_typeSerializer == null) {
ser.serialize(value, jgen, prov);
} else {
ser.serializeWithType(value, jgen, prov, _typeSerializer);
}
}
// need to override as we must get unwrapping instance...
@Override
public void assignSerializer(JsonSerializer<Object> ser)
{
super.assignSerializer(ser);
if (_serializer != null) {
NameTransformer t = _nameTransformer;
if (_serializer.isUnwrappingSerializer()) {
t = NameTransformer.chainedTransformer(t, ((UnwrappingBeanSerializer) _serializer)._nameTransformer);
}
_serializer = _serializer.unwrappingSerializer(t);
}
}
/*
/**********************************************************
/* Overrides: schema generation
/**********************************************************
*/
@Override
public void depositSchemaProperty(final JsonObjectFormatVisitor visitor)
throws JsonMappingException {
SerializerProvider provider = visitor.getProvider();
JsonSerializer<Object> ser = provider
.findValueSerializer(this.getType(), this)
.unwrappingSerializer(_nameTransformer);
if (ser.isUnwrappingSerializer()) {
ser.acceptJsonFormatVisitor(new JsonFormatVisitorWrapper.Base(provider) {
// an unwrapping serializer will always expect ObjectFormat,
// hence, the other cases do not have to be implemented
@Override
public JsonObjectFormatVisitor expectObjectFormat(JavaType type)
throws JsonMappingException {
return visitor;
}
}, this.getType());
} else {
super.depositSchemaProperty(visitor);
}
}
// Override needed to support legacy JSON Schema generator
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
@Override
protected void _depositSchemaProperty(ObjectNode propertiesNode, JsonNode schemaNode)
{
JsonNode props = schemaNode.get("properties");
if (props != null) {
Iterator<Entry<String, JsonNode>> it = props.fields();
while (it.hasNext()) {
Entry<String,JsonNode> entry = it.next();
String name = entry.getKey();
if (_nameTransformer != null) {
name = _nameTransformer.transform(name);
}
propertiesNode.set(name, entry.getValue());
}
}
}
/*
/**********************************************************
/* Overrides: internal, other
/**********************************************************
*/
// need to override as we must get unwrapping instance...
@Override
protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
Class<?> type, SerializerProvider provider) throws JsonMappingException
{
JsonSerializer<Object> serializer;
if (_nonTrivialBaseType != null) {
JavaType subtype = provider.constructSpecializedType(_nonTrivialBaseType, type);
serializer = provider.findValueSerializer(subtype, this);
} else {
serializer = provider.findValueSerializer(type, this);
}
NameTransformer t = _nameTransformer;
if (serializer.isUnwrappingSerializer()) {
t = NameTransformer.chainedTransformer(t, ((UnwrappingBeanSerializer) serializer)._nameTransformer);
}
serializer = serializer.unwrappingSerializer(t);
_dynamicSerializers = _dynamicSerializers.newWith(type, serializer);
return serializer;
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes.
*/
NON_FINAL
}
/**
* Customized {@link TypeResolverBuilder} that provides type resolver builders
* used with so-called "default typing"
* (see {@link ObjectMapper#enableDefaultTyping()} for details).
*<p>
* Type resolver construction is based on configuration: implementation takes care
* of only providing builders in cases where type information should be applied.
* This is important since build calls may be sent for any and all types, and
* type information should NOT be applied to all of them.
*/
public static class DefaultTypeResolverBuilder
extends StdTypeResolverBuilder
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
/**
* Definition of what types is this default typer valid for.
*/
protected final DefaultTyping _appliesFor;
public DefaultTypeResolverBuilder(DefaultTyping t) {
_appliesFor = t;
}
@Override
public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
JavaType baseType, Collection<NamedType> subtypes)
{
return useForType(baseType) ? super.buildTypeDeserializer(config, baseType, subtypes) : null;
}
@Override
public TypeSerializer buildTypeSerializer(SerializationConfig config,
JavaType baseType, Collection<NamedType> subtypes)
{
return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null;
}
/**
* Method called to check if the default type handler should be
* used for given type.
* Note: "natural types" (String, Boolean, Integer, Double) will never
* use typing; that is both due to them being concrete and final,
* and since actual serializers and deserializers will also ignore any
* attempts to enforce typing.
*/
public boolean useForType(JavaType t)
{
switch (_appliesFor) {
case NON_CONCRETE_AND_ARRAYS:
while (t.isArrayType()) {
t = t.getContentType();
}
// fall through
case OBJECT_AND_NON_CONCRETE:
return t.isJavaLangObject()
|| (!t.isConcrete()
// [databind#88] Should not apply to JSON tree models:
&& !TreeNode.class.isAssignableFrom(t.getRawClass()));
case NON_FINAL:
while (t.isArrayType()) {
t = t.getContentType();
}
// [Issue#88] Should not apply to JSON tree models:
return !t.is
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Final() && !TreeNode.class.isAssignableFrom(t.getRawClass());
default:
//case JAVA_LANG_OBJECT:
return t.isJavaLangObject();
}
}
}
/*
/**********************************************************
/* Internal constants, singletons
/**********************************************************
*/
// Quick little shortcut, to avoid having to use global TypeFactory instance...
private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class);
// 16-May-2009, tatu: Ditto ^^^
protected final static AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector();
protected final static VisibilityChecker<?> STD_VISIBILITY_CHECKER = VisibilityChecker.Std.defaultInstance();
protected final static PrettyPrinter _defaultPrettyPrinter = new DefaultPrettyPrinter();
/**
* Base settings contain defaults used for all {@link ObjectMapper}
* instances.
*/
protected final static BaseSettings DEFAULT_BASE = new BaseSettings(
null, // can not share global ClassIntrospector any more (2.5+)
DEFAULT_ANNOTATION_INTROSPECTOR,
STD_VISIBILITY_CHECKER, null, TypeFactory.defaultInstance(),
null, StdDateFormat.instance, null,
Locale.getDefault(),
// TimeZone.getDefault()
TimeZone.getTimeZone("GMT"),
Base64Variants.getDefaultVariant() // 2.1
);
/*
/**********************************************************
/* Configuration settings, shared
/**********************************************************
*/
/**
* Factory used to create {@link JsonParser} and {@link JsonGenerator}
* instances as necessary.
*/
protected final JsonFactory _jsonFactory;
/**
* Specific factory used for creating {@link JavaType} instances;
* needed to allow modules to add more custom type handling
* (mostly to support types of non-Java JVM languages)
*/
protected TypeFactory _typeFactory;
/**
* Provider for values to inject in deserialized POJOs.
*/
protected InjectableValues _injectableValues;
/**
* Thing used for registering sub-types, resolving them to
* super/sub-types as needed.
*/
protected SubtypeResolver _subtypeResolver;
/**
* Cache for root names used when root-wrapping is enabled.
*/
protected final RootNameLookup _rootNames;
/*
/**********************************************************
/* Configuration settings: mix-in annotations
/**********************************************************
*/
/**
* Mapping that defines how to apply mix-in annotations: key is
* the type to received additional annotations, and value is the
* type that has annotations to "mix in".
*<p>
* Annotations
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
*/
public TypeFactory getTypeFactory() {
return _typeFactory;
}
/**
* Method that can be used to override {@link TypeFactory} instance
* used by this mapper.
*<p>
* Note: will also set {@link TypeFactory} that deserialization and
* serialization config objects use.
*/
public ObjectMapper setTypeFactory(TypeFactory f)
{
_typeFactory = f;
_deserializationConfig = _deserializationConfig.with(f);
_serializationConfig = _serializationConfig.with(f);
return this;
}
/**
* Convenience method for constructing {@link JavaType} out of given
* type (typically <code>java.lang.Class</code>), but without explicit
* context.
*/
public JavaType constructType(Type t) {
return _typeFactory.constructType(t);
}
/*
/**********************************************************
/* Configuration, deserialization
/**********************************************************
*/
/**
* Method that can be used to get hold of {@link JsonNodeFactory}
* that this mapper will use when directly constructing
* root {@link JsonNode} instances for Trees.
*<p>
* Note: this is just a shortcut for calling
*<pre>
* getDeserializationConfig().getNodeFactory()
*</pre>
*/
public JsonNodeFactory getNodeFactory() {
return _deserializationConfig.getNodeFactory();
}
/**
* Method for specifying {@link JsonNodeFactory} to use for
* constructing root level tree nodes (via method
* {@link #createObjectNode}
*/
public ObjectMapper setNodeFactory(JsonNodeFactory f) {
_deserializationConfig = _deserializationConfig.with(f);
return this;
}
/**
* Method for adding specified {@link DeserializationProblemHandler}
* to be used for handling specific problems during deserialization.
*/
public ObjectMapper addHandler(DeserializationProblemHandler h) {
_deserializationConfig = _deserializationConfig.withHandler(h);
return this;
}
/**
* Method for removing all registered {@link DeserializationProblemHandler}s
* instances from this mapper.
*/
public ObjectMapper clearProblemHandlers() {
_deserializationConfig = _deserializationConfig.withNoProblemHandlers();
return this;
}
/**
* Method that allows overriding of the underlying {@link DeserializationConfig}
* object.
* It is added as a fallback method that may be used if no other configuration
* modifier method works: it should not be used if there are alternatives,
* and its use is generally discouraged.
*<p>
* <b>NOTE</b>: only use this method if you know what you
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
* @throws IOException if a low-level I/O problem (unexpected end-of-input,
* network error) occurs (passed through as-is without additional wrapping -- note
* that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
* does NOT result in wrapping of exception even if enabled)
* @throws JsonParseException if underlying input contains invalid content
* of type {@link JsonParser} supports (JSON for default case)
* @throws JsonMappingException if the input JSON structure does not match structure
* expected for result type (or has other mismatch issues)
*/
@SuppressWarnings("unchecked")
public <T> T readValue(JsonParser jp, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), jp, valueType);
}
/**
* Method to deserialize JSON content as tree expressed
* using set of {@link JsonNode} instances. Returns
* root of the resulting tree (where root can consist
* of just a single node if the current event is a
* value event, not container).
*
* @return a {@link JsonNode}, if valid JSON content found; null
* if input has no content to bind -- note, however, that if
* JSON <code>null</code> token is found, it will be represented
* as a non-null {@link JsonNode} (one that returns <code>true</code>
* for {@link JsonNode#isNull()}
*
* @throws IOException if a low-level I/O problem (unexpected end-of-input,
* network error) occurs (passed through as-is without additional wrapping -- note
* that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
* does NOT result in wrapping of exception even if enabled)
* @throws JsonParseException if underlying input contains invalid content
* of type {@link JsonParser} supports (JSON for default case)
*/
@Override
public <T extends TreeNode> T readTree(JsonParser jp)
throws IOException, JsonProcessingException
{
/* 02-Mar-2009, tatu: One twist; deserialization provider
* will map JSON null straight into Java null. But what
* we want to return is the "null node" instead.
*/
/* 05-Aug-2011, tatu: Also, must check for EOF here before
* calling readValue(), since that'll choke on it otherwise
*/
DeserializationConfig cfg = getDeserializationConfig();
JsonToken t = jp.getCurrentToken();
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
if (t == null) {
t = jp.nextToken();
if (t == null) {
return null;
}
}
JsonNode n = (JsonNode) _readValue(cfg, jp, JSON_NODE_TYPE);
if (n == null) {
n = getNodeFactory().nullNode();
}
@SuppressWarnings("unchecked")
T result = (T) n;
return result;
}
/**
* Method for reading sequence of Objects from parser stream.
* Sequence can be either root-level "unwrapped" sequence (without surrounding
* JSON array), or a sequence contained in a JSON Array.
* In either case {@link JsonParser} must point to the first token of
* the first element, OR not point to any token (in which case it is advanced
* to the next token). This means, specifically, that for wrapped sequences,
* parser MUST NOT point to the surrounding <code>START_ARRAY</code> but rather
* to the token following it.
*<p>
* Note that {@link ObjectReader} has more complete set of variants.
*/
@Override
public <T> MappingIterator<T> readValues(JsonParser jp, ResolvedType valueType)
throws IOException, JsonProcessingException
{
return readValues(jp, (JavaType) valueType);
}
/**
* Type-safe overloaded method, basically alias for {@link #readValues(JsonParser, ResolvedType)}.
*/
public <T> MappingIterator<T> readValues(JsonParser jp, JavaType valueType)
throws IOException, JsonProcessingException
{
DeserializationConfig config = getDeserializationConfig();
DeserializationContext ctxt = createDeserializationContext(jp, config);
JsonDeserializer<?> deser = _findRootDeserializer(ctxt, valueType);
// false -> do NOT close JsonParser (since caller passed it)
return new MappingIterator<T>(valueType, jp, ctxt, deser,
false, null);
}
/**
* Type-safe overloaded method, basically alias for {@link #readValues(JsonParser, ResolvedType)}.
*/
@Override
public <T> MappingIterator<T> readValues(JsonParser jp, Class<T> valueType)
throws IOException, JsonProcessingException
{
return readValues(jp, _typeFactory.constructType(valueType));
}
/**
* Method for reading sequence of Objects from parser stream.
*/
@Override
public <T> MappingIterator<T> readValues(JsonParser jp, TypeReference<?> valueTypeRef)
throws IOException, JsonProcessingException
{
return readValues(jp, _typeFactory.constructType(valueTypeRef));
}
/*
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>**********************************************************
/* Extended Public API: constructing ObjectReaders
/* for more advanced configuration
/**********************************************************
*/
/**
* Factory method for constructing {@link ObjectReader} with
* default settings. Note that the resulting instance is NOT usable as is,
* without defining expected value type.
*/
@SuppressWarnings("unchecked")
public <T extends ObjectReader> T reader() {
return (T) _newReader(getDeserializationConfig()).with(_injectableValues);
}
/**
* Factory method for constructing {@link ObjectReader} with
* specified feature enabled (compared to settings that this
* mapper instance has).
* Note that the resulting instance is NOT usable as is,
* without defining expected value type.
*/
@SuppressWarnings("unchecked")
public <T extends ObjectReader> T reader(DeserializationFeature feature) {
return (T) _newReader(getDeserializationConfig().with(feature));
}
/**
* Factory method for constructing {@link ObjectReader} with
* specified features enabled (compared to settings that this
* mapper instance has).
* Note that the resulting instance is NOT usable as is,
* without defining expected value type.
*/
@SuppressWarnings("unchecked")
public <T extends ObjectReader> T reader(DeserializationFeature first,
DeserializationFeature... other) {
return (T) _newReader(getDeserializationConfig().with(first, other));
}
/**
* Factory method for constructing {@link ObjectReader} that will
* update given Object (usually Bean, but can be a Collection or Map
* as well, but NOT an array) with JSON data. Deserialization occurs
* normally except that the root-level value in JSON is not used for
* instantiating a new object; instead give updateable object is used
* as root.
* Runtime type of value object is used for locating deserializer,
* unless overridden by other factory methods of {@link ObjectReader}
*/
@SuppressWarnings("unchecked")
public <T extends ObjectReader> T readerForUpdating(Object valueToUpdate) {
JavaType t = _typeFactory.constructType(valueToUpdate.getClass());
return (T) _newReader(getDeserializationConfig(), t, valueToUpdate,
null, _injectableValues);
}
/**
* Factory method for constructing {@link ObjectReader} that will
* read or update instances of specified type
*/
@SuppressWarnings("unchecked")
public <T extends ObjectReader> T reader(JavaType type) {
return (T) _newReader(getDeserializationConfig(), type, null,
null, _injectableValues);
}
/**
* Factory method for constructing {@link ObjectReader} that will
* read or update
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> lose conversions of generic types.
*/
Class<?> targetType = toValueType.getRawClass();
if (targetType != Object.class
&& !toValueType.hasGenericTypes()
&& targetType.isAssignableFrom(fromValue.getClass())) {
return fromValue;
}
/* Then use TokenBuffer, which is a JsonGenerator:
* (see [JACKSON-175])
*/
TokenBuffer buf = new TokenBuffer(this, false);
try {
// inlined 'writeValue' with minor changes:
// first: disable wrapping when writing
SerializationConfig config = getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE);
// no need to check for closing of TokenBuffer
_serializerProvider(config).serializeValue(buf, fromValue);
// then matching read, inlined 'readValue' with minor mods:
final JsonParser jp = buf.asParser();
Object result;
// ok to pass in existing feature flags; unwrapping handled by mapper
final DeserializationConfig deserConfig = getDeserializationConfig();
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
DeserializationContext ctxt = createDeserializationContext(jp, deserConfig);
result = _findRootDeserializer(ctxt, toValueType).getNullValue();
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else { // pointing to event other than null
DeserializationContext ctxt = createDeserializationContext(jp, deserConfig);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, toValueType);
// note: no handling of unwarpping
result = deser.deserialize(jp, ctxt);
}
jp.close();
return result;
} catch (IOException e) { // should not occur, no real i/o...
throw new IllegalArgumentException(e.getMessage(), e);
}
}
/*
/**********************************************************
/* Extended Public API: JSON Schema generation
/**********************************************************
*/
/**
* Generate <a href="http://json-schema.org/">Json-schema</a>
* instance for specified class.
*
* @param t The class to generate schema for
* @return Constructed JSON schema.
*/
@SuppressWarnings("deprecation")
public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class<?> t)
throws JsonMappingException {
return _serializerProvider(getSerializationConfig()).generateJsonSchema(t);
}
/**
* Method for visiting type hierarchy for given type, using specified visitor.
*<p>
* This method can be used for things like
*
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>IOException ioe) { }
}
if (toClose != null) {
try {
toClose.close();
} catch (IOException ioe) { }
}
}
}
/**
* Helper method used when value to serialize is {@link Closeable} and its <code>close()</code>
* method is to be called right after serialization has been called
*/
private final void _writeCloseableValue(JsonGenerator jgen, Object value, SerializationConfig cfg)
throws IOException, JsonGenerationException, JsonMappingException
{
Closeable toClose = (Closeable) value;
try {
_serializerProvider(cfg).serializeValue(jgen, value);
if (cfg.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
jgen.flush();
}
Closeable tmpToClose = toClose;
toClose = null;
tmpToClose.close();
} finally {
if (toClose != null) {
try {
toClose.close();
} catch (IOException ioe) { }
}
}
}
/*
/**********************************************************
/* Internal methods for deserialization, overridable
/**********************************************************
*/
/**
* Internal helper method called to create an instance of {@link DeserializationContext}
* for deserializing a single root value.
* Can be overridden if a custom context is needed.
*/
protected DefaultDeserializationContext createDeserializationContext(JsonParser jp,
DeserializationConfig cfg) {
return _deserializationContext.createInstance(cfg, jp, _injectableValues);
}
/**
* Actual implementation of value reading+binding operation.
*/
protected Object _readValue(DeserializationConfig cfg, JsonParser jp, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
/* First: may need to read the next token, to initialize
* state (either before first read from parser, or after
* previous token has been cleared)
*/
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
// [JACKSON-643]: Ask JsonDeserializer what 'null value' to use:
DeserializationContext ctxt = createDeserializationContext(jp, cfg);
result = _findRootDeserializer(ctxt, valueType).getNullValue();
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else { // pointing to event other than null
DeserializationContext ctxt = createDeserializationContext(jp, cfg);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
// ok, let's
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> get the value
if (cfg.useRootWrapping()) {
result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
} else {
result = deser.deserialize(jp, ctxt);
}
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
}
protected Object _readMapAndClose(JsonParser jp, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
try {
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
// [JACKSON-643]: Ask JsonDeserializer what 'null value' to use:
DeserializationContext ctxt = createDeserializationContext(jp,
getDeserializationConfig());
result = _findRootDeserializer(ctxt, valueType).getNullValue();
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else {
DeserializationConfig cfg = getDeserializationConfig();
DeserializationContext ctxt = createDeserializationContext(jp, cfg);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
if (cfg.useRootWrapping()) {
result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
} else {
result = deser.deserialize(jp, ctxt);
}
ctxt.checkUnresolvedObjectId();
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
} finally {
try {
jp.close();
} catch (IOException ioe) { }
}
}
/**
* Method called to ensure that given parser is ready for reading
* content for data binding.
*
* @return First token to be used for data binding after this call:
* can never be null as exception will be thrown if parser can not
* provide more tokens.
*
* @throws IOException if the underlying input source has problems during
* parsing
* @throws JsonParseException if parser has problems parsing content
* @throws JsonMappingException if the parser does not have any more
* content to map (note: Json "null" value is considered content;
* enf-of-stream not)
*/
protected JsonToken _initForReading(JsonParser p) throws IOException
{
_deserializationConfig.initialize(p); // since 2.5
/* First: must point to a token; if not pointing to one, advance.
* This occurs before first read from JsonParser, as well as
* after clearing of current token.
*/
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> JsonToken t = p.getCurrentToken();
if (t == null) {
// and then we must get something...
t = p.nextToken();
if (t == null) {
/* [JACKSON-546] Throw mapping exception, since it's failure to map,
* not an actual parsing problem
*/
throw JsonMappingException.from(p, "No content to map due to end-of-input");
}
}
return t;
}
protected Object _unwrapAndDeserialize(JsonParser p, DeserializationContext ctxt,
DeserializationConfig config,
JavaType rootType, JsonDeserializer<Object> deser)
throws IOException
{
String expName = config.getRootName();
if (expName == null) {
PropertyName pname = _rootNames.findRootName(rootType, config);
expName = pname.getSimpleName();
}
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw JsonMappingException.from(p, "Current token not START_OBJECT (needed to unwrap root name '"
+expName+"'), but "+p.getCurrentToken());
}
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw JsonMappingException.from(p, "Current token not FIELD_NAME (to contain expected root name '"
+expName+"'), but "+p.getCurrentToken());
}
String actualName = p.getCurrentName();
if (!expName.equals(actualName)) {
throw JsonMappingException.from(p, "Root name '"+actualName+"' does not match expected ('"
+expName+"') for type "+rootType);
}
// ok, then move to value itself....
p.nextToken();
Object result = deser.deserialize(p, ctxt);
// and last, verify that we now get matching END_OBJECT
if (p.nextToken() != JsonToken.END_OBJECT) {
throw JsonMappingException.from(p, "Current token not END_OBJECT (to match wrapper object with root name '"
+expName+"'), but "+p.getCurrentToken());
}
return result;
}
/*
/**********************************************************
/* Internal methods, other
/**********************************************************
*/
/**
* Method called to locate deserializer for the passed root-level value.
*/
protected JsonDeserializer<Object> _findRootDeserializer(DeserializationContext ctxt,
JavaType valueType)
throws JsonMappingException
{
// First: have we already seen it?
JsonDeserializer<Object> deser = _rootDeserializers.get(valueType);
if (deser != null) {
return deser;
}
// Nope:
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> {
/* First: let's ensure property is a container type: caller should have
* verified but just to be sure
*/
if (!containerType.isContainerType()) {
throw new IllegalArgumentException("Must call method with a container type (got "+containerType+")");
}
return _findTypeResolver(config, am, containerType);
}
@Override
public List<NamedType> findSubtypes(Annotated a)
{
JsonSubTypes t = _findAnnotation(a, JsonSubTypes.class);
if (t == null) return null;
JsonSubTypes.Type[] types = t.value();
ArrayList<NamedType> result = new ArrayList<NamedType>(types.length);
for (JsonSubTypes.Type type : types) {
result.add(new NamedType(type.value(), type.name()));
}
return result;
}
@Override
public String findTypeName(AnnotatedClass ac)
{
JsonTypeName tn = _findAnnotation(ac, JsonTypeName.class);
return (tn == null) ? null : tn.value();
}
/*
/**********************************************************
/* Serialization: general annotations
/**********************************************************
*/
@Override
public Object findSerializer(Annotated a)
{
JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
if (ann != null) {
Class<? extends JsonSerializer<?>> serClass = ann.using();
if (serClass != JsonSerializer.None.class) {
return serClass;
}
}
/* 18-Oct-2010, tatu: [JACKSON-351] @JsonRawValue handled just here, for now;
* if we need to get raw indicator from other sources need to add
* separate accessor within {@link AnnotationIntrospector} interface.
*/
JsonRawValue annRaw = _findAnnotation(a, JsonRawValue.class);
if ((annRaw != null) && annRaw.value()) {
// let's construct instance with nominal type:
Class<?> cls = a.getRawType();
return new RawSerializer<Object>(cls);
}
return null;
}
@Override
public Class<? extends JsonSerializer<?>> findKeySerializer(Annotated a)
{
JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
if (ann != null) {
Class<? extends JsonSerializer<?>> serClass = ann.keyUsing();
if (serClass != JsonSerializer.None.class) {
return serClass;
}
}
return null;
}
@Override
public Class<? extends JsonSerializer<?>> findContentSerializer(Annotated a)
{
JsonSerialize ann = _findAnnotation
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> "Can not deserialize instance of "+_calcName(targetClass)+" out of "+token+" token");
}
/**
* Helper method for constructing generic mapping exception with specified
* message and current location information
*/
public JsonMappingException mappingException(String message) {
return JsonMappingException.from(getParser(), message);
}
/**
* Helper method for constructing instantiation exception for specified type,
* to indicate problem with physically constructing instance of
* specified class (missing constructor, exception from constructor)
*/
public JsonMappingException instantiationException(Class<?> instClass, Throwable t) {
return JsonMappingException.from(_parser,
"Can not construct instance of "+instClass.getName()+", problem: "+t.getMessage(), t);
}
public JsonMappingException instantiationException(Class<?> instClass, String msg) {
return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+", problem: "+msg);
}
/**
* Method that will construct an exception suitable for throwing when
* some String values are acceptable, but the one encountered is not.
*
*
* @deprecated Since 2.1 should use variant that takes value
*/
@Deprecated
public JsonMappingException weirdStringException(Class<?> instClass, String msg) {
return weirdStringException(null, instClass, msg);
}
/**
* Method that will construct an exception suitable for throwing when
* some String values are acceptable, but the one encountered is not.
*
* @param value String value from input being deserialized
* @param instClass Type that String should be deserialized into
* @param msg Message that describes specific problem
*
* @since 2.1
*/
public JsonMappingException weirdStringException(String value, Class<?> instClass, String msg) {
return InvalidFormatException.from(_parser,
"Can not construct instance of "+instClass.getName()+" from String value '"+_valueDesc()+"': "+msg,
value, instClass);
}
/**
* Helper method for constructing exception to indicate that input JSON
* Number was not suitable for deserializing into given type.
*/
@Deprecated
public JsonMappingException weirdNumberException(Class<?> instClass, String msg) {
return weirdStringException(null, instClass, msg);
}
/**
* Helper method for constructing exception to indicate that input JSON
* Number was not suitable for deserializing into given target type.
*/
public JsonMappingException weirdNumberException(Number value, Class<?> instClass, String msg) {
return InvalidFormatException.from(_parser,
"Can not construct instance of "+instClass.getName()+" from number value ("+_valueDesc
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>field;
_serializer = base._serializer;
_nullSerializer = base._nullSerializer;
// one more thing: copy internal settings, if any (since 1.7)
if (base._internalSettings != null) {
_internalSettings = new HashMap<Object,Object>(base._internalSettings);
}
_cfgSerializationType = base._cfgSerializationType;
_dynamicSerializers = base._dynamicSerializers;
_suppressNulls = base._suppressNulls;
_suppressableValue = base._suppressableValue;
_includeInViews = base._includeInViews;
_typeSerializer = base._typeSerializer;
_nonTrivialBaseType = base._nonTrivialBaseType;
_metadata = base._metadata;
}
public BeanPropertyWriter rename(NameTransformer transformer) {
String newName = transformer.transform(_name.getValue());
if (newName.equals(_name.toString())) {
return this;
}
return new BeanPropertyWriter(this, new PropertyName(newName));
}
/**
* Method called to assign value serializer for property
*
* @since 2.0
*/
public void assignSerializer(JsonSerializer<Object> ser) {
// may need to disable check in future?
if (_serializer != null && _serializer != ser) {
throw new IllegalStateException("Can not override serializer");
}
_serializer = ser;
}
/**
* Method called to assign null value serializer for property
*
* @since 2.0
*/
public void assignNullSerializer(JsonSerializer<Object> nullSer) {
// may need to disable check in future?
if (_nullSerializer != null && _nullSerializer != nullSer) {
throw new IllegalStateException("Can not override null serializer");
}
_nullSerializer = nullSer;
}
/**
* Method called create an instance that handles details of unwrapping
* contained value.
*/
public BeanPropertyWriter unwrappingWriter(NameTransformer unwrapper) {
return new UnwrappingBeanPropertyWriter(this, unwrapper);
}
/**
* Method called to define type to consider as "non-trivial" basetype,
* needed for dynamic serialization resolution for complex (usually container)
* types
*/
public void setNonTrivialBaseType(JavaType t) {
_nonTrivialBaseType = t;
}
/*
/**********************************************************
/* BeanProperty impl
/**********************************************************
*/
// Note: also part of 'PropertyWriter'
@Override public String getName() { return _name.getValue(); }
// Note: also part of 'PropertyWriter'
@Override public PropertyName getFullName() { // !!! TODO: impl properly
return
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>SchemaProperty(ObjectNode propertiesNode, SerializerProvider provider)
throws JsonMappingException
{
JavaType propType = getSerializationType();
// 03-Dec-2010, tatu: SchemaAware REALLY should use JavaType, but alas it doesn't...
Type hint = (propType == null) ? getGenericPropertyType() : propType.getRawClass();
JsonNode schemaNode;
// Maybe it already has annotated/statically configured serializer?
JsonSerializer<Object> ser = getSerializer();
if (ser == null) { // nope
ser = provider.findValueSerializer(getType(), this);
}
boolean isOptional = !isRequired();
if (ser instanceof SchemaAware) {
schemaNode = ((SchemaAware) ser).getSchema(provider, hint, isOptional) ;
} else {
schemaNode = com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
}
_depositSchemaProperty(propertiesNode, schemaNode);
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
Class<?> type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result;
if (_nonTrivialBaseType != null) {
JavaType t = provider.constructSpecializedType(_nonTrivialBaseType, type);
result = map.findAndAddPrimarySerializer(t, provider, this);
} else {
result = map.findAndAddPrimarySerializer(type, provider, this);
}
// did we get a new map of serializers? If so, start using it
if (map != result.map) {
_dynamicSerializers = result.map;
}
return result.serializer;
}
/**
* Method that can be used to access value of the property this
* Object describes, from given bean instance.
*<p>
* Note: method is final as it should not need to be overridden -- rather,
* calling method(s) ({@link #serializeAsField}) should be overridden
* to change the behavior
*/
public final Object get(Object bean) throws Exception {
return (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean);
}
/**
* Method called to handle a direct self-reference through this property.
* Method can choose to indicate an error by throwing {@link JsonMappingException};
* fully handle serialization (and return true); or indicate that it should be
* serialized normally (return false).
*<p>
* Default implementation will throw {@link JsonMappingException} if
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (jp.canReadTypeId()) {
Object typeId = jp.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(jp, ctxt, typeId);
}
}
boolean hadStartArray = jp.isExpectedStartArrayToken();
String typeId = _locateTypeId(jp, ctxt);
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
// Minor complication: we may need to merge type id in?
if (_typeIdVisible
// 06-Oct-2014, tatu: To fix [databind#408], must distinguish between
// internal and external properties
// TODO: but does it need to be injected in external case? Why not?
&& !_usesExternalId()
&& jp.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
jp = JsonParserSequence.createFlattened(tb.asParser(jp), jp);
jp.nextToken();
}
Object value = deser.deserialize(jp, ctxt);
// And then need the closing END_ARRAY
if (hadStartArray && jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"expected closing END_ARRAY after type information and deserialized value");
}
return value;
}
protected final String _locateTypeId(JsonParser jp, DeserializationContext ctxt) throws IOException
{
if (!jp.isExpectedStartArrayToken()) {
// Need to allow even more customized handling, if something unexpected seen...
// but should there be a way to limit this to likely success cases?
if (_defaultImpl != null) {
return _idResolver.idFromBaseType();
}
throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "need JSON Array to contain As.WRAPPER_ARRAY type information for class "+baseTypeName());
}
// And then type id as a String
JsonToken t = jp.nextToken();
if (t == JsonToken.VALUE_STRING) {
String result = jp.getText();
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
/**
* Intermediate base deserializer class that adds more shared accessor
* so that other classes can access information about contained (value)
* types
*/
@SuppressWarnings("serial")
public abstract class ContainerDeserializerBase<T>
extends StdDeserializer<T>
{
protected ContainerDeserializerBase(JavaType selfType) {
super(selfType);
}
/**
* @deprecated Since 2.3 use one that takes {@link JavaType}
*/
@Deprecated
protected ContainerDeserializerBase(Class<?> selfType) {
super(selfType);
}
/*
/**********************************************************
/* Overrides
/**********************************************************
*/
@Override
public SettableBeanProperty findBackReference(String refName) {
JsonDeserializer<Object> valueDeser = getContentDeserializer();
if (valueDeser == null) {
throw new IllegalArgumentException("Can not handle managed/back reference '"+refName
+"': type: container deserializer of type "+getClass().getName()+" returned null for 'getContentDeserializer()'");
}
return valueDeser.findBackReference(refName);
}
/*
/**********************************************************
/* Extended API
/**********************************************************
*/
/**
* Accessor for declared type of contained value elements; either exact
* type, or one of its supertypes.
*/
public abstract JavaType getContentType();
/**
* Accesor for deserializer use for deserializing content values.
*/
public abstract JsonDeserializer<Object> getContentDeserializer();
/*
/**********************************************************
/* Shared methods for sub-classes
/**********************************************************
*/
/**
* Helper method called by various Map(-like) deserializers.
*/
protected void wrapAndThrow(Throwable t, Object ref, String key) throws IOException
{
// to handle StackOverflow:
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// ... except for mapping exceptions
if (t instanceof IOException && !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
throw JsonMappingException.wrapWithPath(t, ref, key);
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
@SuppressWarnings("serial")
public abstract class StdScalarSerializer<T>
extends StdSerializer<T>
{
protected StdScalarSerializer(Class<T> t) {
super(t);
}
/**
* Alternate constructor that is (alas!) needed to work
* around kinks of generic type handling
*/
@SuppressWarnings("unchecked")
protected StdScalarSerializer(Class<?> t, boolean dummy) {
super((Class<T>) t);
}
/**
* Default implementation will write type prefix, call regular serialization
* method (since assumption is that value itself does not need JSON
* Array or Object start/end markers), and then write type suffix.
* This should work for most cases; some sub-classes may want to
* change this behavior.
*/
@Override
public void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer) throws IOException
{
typeSer.writeTypePrefixForScalar(value, jgen);
serialize(value, jgen, provider);
typeSer.writeTypeSuffixForScalar(value, jgen);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
if (visitor != null) {
// 13-Sep-2013, tatu: Let's assume it's usually a String, right?
// visitor.expectAnyFormat(typeHint);
visitor.expectStringFormat(typeHint);
}
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>() {
return _type;
}
@Override
public Class<?> getRawType()
{
if (_type instanceof Class<?>) {
return (Class<?>) _type;
}
// 14-Mar-2011, tatu: Not optimal, but has to do for now...
JavaType t = TypeFactory.defaultInstance().constructType(_type);
return t.getRawClass();
}
/*
/**********************************************************
/* AnnotatedMember extras
/**********************************************************
*/
@Override
public Class<?> getDeclaringClass() {
return _owner.getDeclaringClass();
}
@Override
public Member getMember() {
/* This is bit tricky: since there is no JDK equivalent; can either
* return null or owner... let's do latter, for now.
*/
return _owner.getMember();
}
@Override
public void setValue(Object pojo, Object value) throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Cannot call setValue() on constructor parameter of "
+getDeclaringClass().getName());
}
@Override
public Object getValue(Object pojo) throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Cannot call getValue() on constructor parameter of "
+getDeclaringClass().getName());
}
/*
/**********************************************************
/* Extended API
/**********************************************************
*/
public Type getParameterType() { return _type; }
/**
* Accessor for 'owner' of this parameter; method or constructor that
* has this parameter as member of its argument list.
*
* @return Owner (member or creator) object of this parameter
*/
public AnnotatedWithParams getOwner() { return _owner; }
/**
* Accessor for index of this parameter within argument list
*
* @return Index of this parameter within argument list
*/
public int getIndex() { return _index; }
/*
/********************************************************
/* Other
/********************************************************
*/
@Override
public int hashCode() {
return _owner.hashCode() + _index;
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (o == null || o.getClass() != getClass()) return false;
AnnotatedParameter other = (AnnotatedParameter) o;
return other._owner.equals(_owner) && (other._index == _index);
}
@Override
public String toString() {
return "[parameter #"+getIndex()+", annotations: "+_annotations+"]";
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> check to ensure we have START_OBJECT or FIELD_NAME
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
} else if (t == JsonToken.START_ARRAY) {
/* This is most likely due to the fact that not all Java types are
* serialized as JSON Objects; so if "as-property" inclusion is requested,
* serialization of things like Lists must be instead handled as if
* "as-wrapper-array" was requested.
* But this can also be due to some custom handling: so, if "defaultImpl"
* is defined, it will be asked to handle this case.
*/
return _deserializeTypedUsingDefaultImpl(jp, ctxt, null);
} else if (t != JsonToken.FIELD_NAME) {
return _deserializeTypedUsingDefaultImpl(jp, ctxt, null);
}
// Ok, let's try to find the property. But first, need token buffer...
TokenBuffer tb = null;
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String name = jp.getCurrentName();
jp.nextToken(); // to point to the value
if (_typePropertyName.equals(name)) { // gotcha!
return _deserializeTypedForId(jp, ctxt, tb);
}
if (tb == null) {
tb = new TokenBuffer(null, false);
}
tb.writeFieldName(name);
tb.copyCurrentStructure(jp);
}
return _deserializeTypedUsingDefaultImpl(jp, ctxt, tb);
}
@SuppressWarnings("resource")
protected final Object _deserializeTypedForId(JsonParser jp, DeserializationContext ctxt, TokenBuffer tb) throws IOException
{
String typeId = jp.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
if (_typeIdVisible) { // need to merge id back in JSON input?
if (tb == null) {
tb = new TokenBuffer(null, false);
}
tb.writeFieldName(jp.getCurrentName());
tb.writeString(typeId);
}
if (tb != null) { // need to put back skipped properties?
jp = JsonParserSequence.createFlattened(tb.asParser(jp), jp);
}
// Must point to the next value; tb had no current, jp pointed to VALUE_STRING:
jp.nextToken(); // to skip past String value
// deserializer should take care of closing END_OBJECT as well
return deser.deserialize(jp, ctxt);
}
// off-lined to keep main method lean and mean...
@SuppressWarnings
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsonschema.SchemaAware;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.Converter;
/**
* Base class used by all standard serializers, and can also
* be used for custom serializers (in fact, this is the recommended
* base class to use).
* Provides convenience methods for implementing {@link SchemaAware}
*/
public abstract class StdSerializer<T>
extends JsonSerializer<T>
implements JsonFormatVisitable, SchemaAware, java.io.Serializable
{
private static final long serialVersionUID = 1L;
/**
* Nominal type supported, usually declared type of
* property for which serializer is used.
*/
protected final Class<T> _handledType;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
protected StdSerializer(Class<T> t) {
_handledType = t;
}
@SuppressWarnings("unchecked")
protected StdSerializer(JavaType type) {
_handledType = (Class<T>) type.getRawClass();
}
/**
* Alternate constructor that is (alas!) needed to work
* around kinks of generic type handling
*/
@SuppressWarnings("unchecked")
protected StdSerializer(Class<?> t, boolean dummy) {
_handledType = (Class<T>) t;
}
/*
/**********************************************************
/* Accessors
/**********************************************************
*/
@Override
public Class<T> handledType() { return _handledType; }
/*
/**********************************************************
/* Serialization
/**********************************************************
*/
@Override
public abstract void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException;
/*
/
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>**********************************************************
/* Helper methods for JSON Schema generation
/**********************************************************
*/
/**
* Default implementation simply claims type is "string"; usually
* overriden by custom serializers.
*/
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
return createSchemaNode("string");
}
/**
* Default implementation simply claims type is "string"; usually
* overriden by custom serializers.
*/
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint, boolean isOptional)
throws JsonMappingException
{
ObjectNode schema = (ObjectNode) getSchema(provider, typeHint);
if (!isOptional) {
schema.put("required", !isOptional);
}
return schema;
}
protected ObjectNode createObjectNode() {
return JsonNodeFactory.instance.objectNode();
}
protected ObjectNode createSchemaNode(String type)
{
ObjectNode schema = createObjectNode();
schema.put("type", type);
return schema;
}
protected ObjectNode createSchemaNode(String type, boolean isOptional)
{
ObjectNode schema = createSchemaNode(type);
// as per [JACKSON-563]. Note that 'required' defaults to false
if (!isOptional) {
schema.put("required", !isOptional);
}
return schema;
}
/**
* Default implementation specifies no format. This behavior is usually
* overriden by custom serializers.
*/
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectAnyFormat(typeHint);
}
/*
/**********************************************************
/* Helper methods for exception handling
/**********************************************************
*/
/**
* Method that will modify caught exception (passed in as argument)
* as necessary to include reference information, and to ensure it
* is a subtype of {@link IOException}, or an unchecked exception.
*<p>
* Rules for wrapping and unwrapping are bit complicated; essentially:
*<ul>
* <li>Errors are to be passed as is (if uncovered via unwrapping)
* <li>"Plain" IOExceptions (ones that are not of type
* {@link JsonMappingException} are to be passed as is
*</ul>
*/
public void wrapAndThrow(SerializerProvider provider,
Throwable t, Object bean, String fieldName)
throws IOException
{
/* 05-Mar-2009, tatu: But one nasty edge is when we get
* StackOverflow: usually due to infinite loop. But that
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
* usually gets hidden within an InvocationTargetException...
*/
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// Ditto for IOExceptions... except for mapping exceptions!
boolean wrap = (provider == null) || provider.isEnabled(SerializationFeature.WRAP_EXCEPTIONS);
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
}
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(t, bean, fieldName);
}
public void wrapAndThrow(SerializerProvider provider,
Throwable t, Object bean, int index)
throws IOException
{
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors are to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// Ditto for IOExceptions... except for mapping exceptions!
boolean wrap = (provider == null) || provider.isEnabled(SerializationFeature.WRAP_EXCEPTIONS);
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
}
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(t, bean, index);
}
/*
/**********************************************************
/* Helper methods, other
/**********************************************************
*/
/**
* Method that can be called to determine if given serializer is the default
* serializer Jackson uses; as opposed to a custom serializer installed by
* a module or calling application. Determination is done using
* {@link JacksonStdImpl} annotation on serializer class.
*/
protected boolean isDefaultSerializer(JsonSerializer<?> serializer) {
return ClassUtil.isJacksonStdImpl(serializer);
}
/**
* Helper method that can be used to see if specified property has annotation
* indicating that a converter is to be used for contained values (contents
* of structured types; array/
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> p, DeserializationContext ctxt,
Collection<Object> result)
throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!p.isExpectedStartArrayToken()) {
return handleNonArray(p, ctxt, result);
}
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(result);
JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
CollectionReferringAccumulator referringAccumulator =
(valueDes.getObjectIdReader() == null) ? null :
new CollectionReferringAccumulator(_collectionType.getContentType().getRawClass(), result);
JsonToken t;
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
try {
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(p, ctxt);
} else {
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
}
if (referringAccumulator != null) {
referringAccumulator.add(value);
} else {
result.add(value);
}
} catch (UnresolvedForwardReference reference) {
if (referringAccumulator == null) {
throw JsonMappingException
.from(p, "Unresolved forward reference but no identity info", reference);
}
Referring ref = referringAccumulator.handleUnresolvedReference(reference);
reference.getRoid().appendReferring(ref);
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException
{
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
/**
* Helper method called when current token is no START_ARRAY. Will either
* throw an exception, or try to handle value as if member of implicit
* array, depending on configuration.
*/
protected final Collection<Object> handleNonArray(JsonParser p, DeserializationContext ctxt,
Collection<Object> result)
throws IOException
{
// [JACKSON-526]: implicit arrays from single values?
if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
throw ctxt.mappingException(_collectionType.getRawClass());
}
Json
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Deserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
JsonToken t = p.getCurrentToken();
Object value;
try {
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(p, ctxt);
} else {
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
}
} catch (Exception e) {
// note: pass Object.class, not Object[].class, as we need element type for error info
throw JsonMappingException.wrapWithPath(e, Object.class, result.size());
}
result.add(value);
return result;
}
public final static class CollectionReferringAccumulator {
private final Class<?> _elementType;
private final Collection<Object> _result;
/**
* A list of {@link CollectionReferring} to maintain ordering.
*/
private List<CollectionReferring> _accumulator = new ArrayList<CollectionReferring>();
public CollectionReferringAccumulator(Class<?> elementType, Collection<Object> result) {
_elementType = elementType;
_result = result;
}
public void add(Object value)
{
if (_accumulator.isEmpty()) {
_result.add(value);
} else {
CollectionReferring ref = _accumulator.get(_accumulator.size() - 1);
ref.next.add(value);
}
}
public Referring handleUnresolvedReference(UnresolvedForwardReference reference)
{
CollectionReferring id = new CollectionReferring(this, reference, _elementType);
_accumulator.add(id);
return id;
}
public void resolveForwardReference(Object id, Object value) throws IOException
{
Iterator<CollectionReferring> iterator = _accumulator.iterator();
// Resolve ordering after resolution of an id. This mean either:
// 1- adding to the result collection in case of the first unresolved id.
// 2- merge the content of the resolved id with its previous unresolved id.
Collection<Object> previous = _result;
while (iterator.hasNext()) {
CollectionReferring ref = iterator.next();
if (ref.hasId(id)) {
iterator.remove();
previous.add(value);
previous.addAll(ref.next);
return;
}
previous = ref.next;
}
throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id
+ "] that wasn't previously seen as unresolved.");
}
}
/**
* Helper class to maintain processing order
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
}
/**
* Specialized method for removing specified existing entry.
* NOTE: entry MUST exist, otherwise an exception is thrown.
*/
public void remove(SettableBeanProperty property)
{
// Mostly this is the same as code with 'replace', just bit simpler...
String name = getPropertyName(property);
int index = name.hashCode() & (_buckets.length-1);
Bucket tail = null;
boolean found = false;
// slightly complex just because chain is immutable, must recreate
for (Bucket bucket = _buckets[index]; bucket != null; bucket = bucket.next) {
// match to remove?
if (!found && bucket.key.equals(name)) {
found = true;
} else {
tail = new Bucket(tail, bucket.key, bucket.value, bucket.index);
}
}
if (!found) { // must be found
throw new NoSuchElementException("No entry '"+property+"' found, can't remove");
}
_buckets[index] = tail;
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
private SettableBeanProperty _findWithEquals(String key, int index)
{
Bucket bucket = _buckets[index];
while (bucket != null) {
if (key.equals(bucket.key)) {
return bucket.value;
}
bucket = bucket.next;
}
return null;
}
/**
* @since 2.5
*/
protected void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)
throws IOException
{
// inlined 'throwOrReturnThrowable'
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// StackOverflowErrors are tricky ones; need to be careful...
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
// Ditto for IOExceptions; except we may want to wrap JSON exceptions
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonProcessingException)) {
throw (IOException) t;
}
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
}
throw JsonMappingException.wrapWithPath(t, bean, fieldName);
}
/*
/**********************************************************
/* Helper beans
/**********************************************************
*/
private final static class Bucket
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Deserializer;
// #125: May have a content converter
deser = findConvertingContentDeserializer(ctxt, property, deser);
final JavaType vt = _arrayType.getContentType();
if (deser == null) {
deser = ctxt.findContextualValueDeserializer(vt, property);
} else { // if directly assigned, probably not yet contextual, so:
deser = ctxt.handleSecondaryContextualization(deser, property, vt);
}
TypeDeserializer elemTypeDeser = _elementTypeDeserializer;
if (elemTypeDeser != null) {
elemTypeDeser = elemTypeDeser.forProperty(property);
}
return withDeserializer(elemTypeDeser, deser);
}
@Override // since 2.5
public boolean isCachable() {
// Important: do NOT cache if polymorphic values, or ones with custom deserializer
return (_elementDeserializer == null) && (_elementTypeDeserializer == null);
}
/*
/**********************************************************
/* ContainerDeserializerBase API
/**********************************************************
*/
@Override
public JavaType getContentType() {
return _arrayType.getContentType();
}
@Override
public JsonDeserializer<Object> getContentDeserializer() {
return _elementDeserializer;
}
/*
/**********************************************************
/* JsonDeserializer API
/**********************************************************
*/
@Override
public Object[] deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
final TypeDeserializer typeDeser = _elementTypeDeserializer;
try {
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Note: must handle null explicitly here; value deserializers won't
Object value;
if (t == JsonToken.VALUE_NULL) {
value = _elementDeserializer.getNullValue();
} else if (typeDeser == null) {
value = _elementDeserializer.deserialize(jp, ctxt);
} else {
value = _elementDeserializer.deserializeWithType(jp, ctxt, typeDeser);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>);
}
Object[] result;
if (_untyped) {
result = buffer.completeAndClearBuffer(chunk, ix);
} else {
result = buffer.completeAndClearBuffer(chunk, ix, _elementClass);
}
ctxt.returnObjectBuffer(buffer);
return result;
}
@Override
public Object[] deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
/* Should there be separate handling for base64 stuff?
* for now this should be enough:
*/
return (Object[]) typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected Byte[] deserializeFromBase64(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// First same as what PrimitiveArrayDeserializers.ByteDeser does:
byte[] b = jp.getBinaryValue(ctxt.getBase64Variant());
// But then need to convert to wrappers
Byte[] result = new Byte[b.length];
for (int i = 0, len = b.length; i < len; ++i) {
result[i] = Byte.valueOf(b[i]);
}
return result;
}
private final Object[] handleNonArray(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// [JACKSON-620] Empty String can become null...
if ((jp.getCurrentToken() == JsonToken.VALUE_STRING)
&& ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
String str = jp.getText();
if (str.length() == 0) {
return null;
}
}
// Can we do implicit coercion to a single-element array still?
if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
/* 04-Oct-2009, tatu: One exception; byte arrays are generally
* serialized as base64, so that should be handled
*/
if (jp.getCurrentToken() == JsonToken.VALUE_STRING
&& _elementClass == Byte.class) {
return deserializeFromBase64(jp, ctxt);
}
throw ctxt.mappingException(_arrayType.getRawClass());
}
JsonToken t = jp.getCurrentToken();
Object value;
if (t == JsonToken.VALUE_NULL) {
value = _elementDeserializer.getNullValue();
} else if (_elementTypeDeserializer == null) {
value = _
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Props) {
super(src, ignorableProps);
}
@Override
public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
{
/* bit kludgy but we don't want to accidentally change type; sub-classes
* MUST override this method to support unwrapped properties...
*/
if (getClass() != BeanDeserializer.class) {
return this;
}
/* main thing really is to just enforce ignoring of unknown
* properties; since there may be multiple unwrapped values
* and properties for all may be interleaved...
*/
return new BeanDeserializer(this, unwrapper);
}
@Override
public BeanDeserializer withObjectIdReader(ObjectIdReader oir) {
return new BeanDeserializer(this, oir);
}
@Override
public BeanDeserializer withIgnorableProperties(HashSet<String> ignorableProps) {
return new BeanDeserializer(this, ignorableProps);
}
@Override
protected BeanDeserializerBase asArrayDeserializer() {
SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
return new BeanAsArrayDeserializer(this, props);
}
/*
/**********************************************************
/* JsonDeserializer implementation
/**********************************************************
*/
/**
* Main deserialization method for bean-based objects (POJOs).
*<p>
* NOTE: was declared 'final' in 2.2; should NOT be to let extensions
* like Afterburner change definition.
*/
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException
{
JsonToken t = p.getCurrentToken();
// common case first
if (t == JsonToken.START_OBJECT) { // TODO: in 2.6, use 'p.hasTokenId()'
if (_vanillaProcessing) {
return vanillaDeserialize(p, ctxt, p.nextToken());
}
p.nextToken();
if (_objectIdReader != null) {
return deserializeWithObjectId(p, ctxt);
}
return deserializeFromObject(p, ctxt);
}
return _deserializeOther(p, ctxt, t);
}
protected final Object _deserializeOther(JsonParser p, DeserializationContext ctxt,
JsonToken t) throws IOException
{
// and then others, generally requiring use of @JsonCreator
switch (t) {
case VALUE_STRING:
return deserializeFromString(p, ctxt);
case VALUE_NUMBER_INT:
return deserializeFromNumber(p, ctxt);
case VALUE_NUMBER_FLOAT:
return deserializeFromDouble(p, ctxt);
case VALUE_EMBEDDED_OBJECT:
return deserializeFromEmbedded(p, ctxt);
case VALUE_TRUE:
case
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> VALUE_FALSE:
return deserializeFromBoolean(p, ctxt);
case START_ARRAY:
// these only work if there's a (delegating) creator...
return deserializeFromArray(p, ctxt);
case FIELD_NAME:
case END_OBJECT: // added to resolve [JACKSON-319], possible related issues
if (_vanillaProcessing) {
return vanillaDeserialize(p, ctxt, t);
}
if (_objectIdReader != null) {
return deserializeWithObjectId(p, ctxt);
}
return deserializeFromObject(p, ctxt);
default:
throw ctxt.mappingException(handledType());
}
}
protected Object _missingToken(JsonParser p, DeserializationContext ctxt)
throws JsonProcessingException
{
throw ctxt.endOfInputException(handledType());
}
/**
* Secondary deserialization method, called in cases where POJO
* instance is created as part of deserialization, potentially
* after collecting some or all of the properties to set.
*/
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt, Object bean)
throws IOException
{
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(bean);
if (_injectables != null) {
injectValues(ctxt, bean);
}
if (_unwrappedPropertyHandler != null) {
return deserializeWithUnwrapped(p, ctxt, bean);
}
if (_externalTypeIdHandler != null) {
return deserializeWithExternalTypeId(p, ctxt, bean);
}
JsonToken t = p.getCurrentToken();
// 23-Mar-2010, tatu: In some cases, we start with full JSON object too...
if (t == JsonToken.START_OBJECT) {
t = p.nextToken();
}
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(p, ctxt, bean, view);
}
}
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken();
if (!_beanProperties.findDeserializeAndSet(p, ctxt, bean, propName)) {
handleUnknownVanilla(p, ctxt, bean, propName);
}
}
return bean;
}
/*
/**********************************************************
/* Concrete deserialization methods
/**********************************************************
*/
/**
* Streamlined version that is only used when no "special"
* features are enabled.
*/
private final Object vanillaDeserialize(JsonParser p,
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>DeserializationContext ctxt, JsonToken t)
throws IOException
{
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(bean);
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken();
if (!_beanProperties.findDeserializeAndSet(p, ctxt, bean, propName)) {
handleUnknownVanilla(p, ctxt, bean, propName);
}
}
// 13-Dec-2014, tatu: For 2.6, we'll do:
/*
if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
String propName = p.getCurrentName();
do {
p.nextToken();
if (!_beanProperties.findDeserializeAndSet(p, ctxt, bean, propName)) {
handleUnknownVanilla(p, ctxt, bean, propName);
}
} while ((propName = p.nextFieldName()) != null);
}
*/
return bean;
}
/**
* General version used when handling needs more advanced features.
*/
@Override
public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException
{
/* 09-Dec-2014, tatu: As per [#622], we need to allow Object Id references
* to come in as JSON Objects as well; but for now assume they will
* be simple, single-property references, which means that we can
* recognize them without having to buffer anything.
* Once again, if we must, we can do more complex handling with buffering,
* but let's only do that if and when that becomes necessary.
*/
if (_objectIdReader != null && _objectIdReader.maySerializeAsObject()) {
// TODO: in 2.6, use 'p.hasTokenId()'
if ((p.getCurrentTokenId() == JsonTokenId.ID_FIELD_NAME)
&& _objectIdReader.isValidReferencePropertyName(p.getCurrentName(), p)) {
return deserializeFromObjectId(p, ctxt);
}
}
if (_nonStandardCreation) {
if (_unwrappedPropertyHandler != null) {
return deserializeWithUnwrapped(p, ctxt);
}
if (_externalTypeIdHandler != null) {
return deserializeWithExternalTypeId(p, ctxt);
}
Object bean = deserializeFromObjectUsingNonDefault(p, ctxt);
if (_injectables != null) {
injectValues(ctxt, bean
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>);
}
/* 27-May-2014, tatu: I don't think view processing would work
* at this point, so commenting it out; but leaving in place
* just in case I forgot something fundamental...
*/
/*
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(p, ctxt, bean, view);
}
}
*/
return bean;
}
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
// [databind#631]: Assign current value, to be accessible by custom deserializers
p.setCurrentValue(bean);
if (p.canReadObjectId()) {
Object id = p.getObjectId();
if (id != null) {
_handleTypedObjectId(p, ctxt, bean, id);
}
}
if (_injectables != null) {
injectValues(ctxt, bean);
}
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(p, ctxt, bean, view);
}
}
JsonToken t = p.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken();
if (!_beanProperties.findDeserializeAndSet(p, ctxt, bean, propName)) {
handleUnknownVanilla(p, ctxt, bean, propName);
}
}
// 13-Dec-2014, tatu: For 2.6, we'll do:
/*
if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
String propName = p.getCurrentName();
do {
p.nextToken();
if (!_beanProperties.findDeserializeAndSet(p, ctxt, bean, propName)) {
handleUnknownVanilla(p, ctxt, bean, propName);
}
} while ((propName = p.nextFieldName()) != null);
}
*/
return bean;
}
/**
* Method called to deserialize bean using "property-based creator":
* this means that a non-default constructor or factory method is
* called, and then possibly other setters. The trick is that
* values for creator method need to be buffered, first; and
* due to non-guaranteed ordering possibly some other properties
* as well.
*/
@Override
@SuppressWarnings("resource")
protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deserial
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>izationContext ctxt)
throws IOException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
// 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
TokenBuffer unknown = null;
JsonToken t = p.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
bean = null; // never gets here
}
if (bean == null) {
throw ctxt.instantiationException(_beanType.getRawClass(), "JSON Creator returned null");
}
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(bean);
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(p, ctxt, bean, unknown);
}
if (unknown != null) { // nope, just extra unknown stuff...
bean = handleUnknownProperties(ctxt, bean, unknown);
}
// or just clean?
return deserialize(p, ctxt, bean);
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop,
deserializeWithErrorWrapping(prop, p, ctxt, propName));
continue;
}
// As per [JACKSON-313], things marked as ignorable should not be
// passed to any setter
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(p, ctxt, handledType(), propName);
continue;
}
// "any property"?
if (_anySetter != null) {
try {
buffer
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt));
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
}
continue;
}
// Ok then, let's collect the whole field; name and value
if (unknown == null) {
unknown = new TokenBuffer(p);
}
unknown.writeFieldName(propName);
unknown.copyCurrentStructure(p);
}
// We hit END_OBJECT, so:
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
bean = null; // never gets here
}
if (unknown != null) {
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(null, ctxt, bean, unknown);
}
// no, just some extra unknown properties
return handleUnknownProperties(ctxt, bean, unknown);
}
return bean;
}
protected Object deserializeWithErrorWrapping(SettableBeanProperty prop,
JsonParser p, DeserializationContext ctxt, String propName) throws IOException
{
try {
return prop.deserialize(p, ctxt);
} catch (IOException e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
// exception below will be throw only if someone overwrite default implementation of wrapAndThrow method
throw e;
}
}
/*
/**********************************************************
/* Deserializing when we have to consider an active View
/**********************************************************
*/
protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt,
Object bean, Class<?> activeView)
throws IOException
{
JsonToken t = p.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
// Skip field name:
p.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
if (!prop.visibleInView(activeView)) {
p.skipChildren();
continue;
}
try {
prop.deserializeAndSet(p, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(p, ctxt, bean, propName);
}
return bean;
}
/*
/**********************************************************
/* Handling for cases where we have "unwrapped" values
/**********************************************************
*/
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
/**
* Method called when there are declared "unwrapped" properties
* which need special handling
*/
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt)
throws IOException
{
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
}
if (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithUnwrapped(p, ctxt);
}
TokenBuffer tokens = new TokenBuffer(p);
tokens.writeStartObject();
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(bean);
if (_injectables != null) {
injectValues(ctxt, bean);
}
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
JsonToken t = p.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView)) {
p.skipChildren();
continue;
}
try {
prop.deserializeAndSet(p, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// ignorable things should be ignored
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(p, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(p);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
try {
_anySetter.deserializeAndSet(p, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt, Object bean)
throws IOException
{
JsonToken t = p.getCurrentToken();
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
if (t == JsonToken.START_OBJECT) {
t = p.nextToken();
}
TokenBuffer tokens = new TokenBuffer(p);
tokens.writeStartObject();
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
SettableBeanProperty prop = _beanProperties.find(propName);
p.nextToken();
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView)) {
p.skipChildren();
continue;
}
try {
prop.deserializeAndSet(p, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(p, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(p);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
_anySetter.deserializeAndSet(p, ctxt, bean, propName);
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, DeserializationContext ctxt)
throws IOException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
TokenBuffer tokens = new TokenBuffer(p);
tokens.writeStartObject();
JsonToken t = p.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt,
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
continue; // never gets here
}
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(bean);
// if so, need to copy all remaining tokens into buffer
while (t == JsonToken.FIELD_NAME) {
p.nextToken(); // to skip name
tokens.copyCurrentStructure(p);
t = p.nextToken();
}
tokens.writeEndObject();
if (bean.getClass() != _beanType.getRawClass()) {
// !!! 08-Jul-2011, tatu: Could probably support; but for now
// it's too complicated, so bail out
tokens.close();
throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
}
return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop,
deserializeWithErrorWrapping(prop, p, ctxt, propName));
continue;
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(p, ctxt, handledType(), propName);
continue;
}
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(p);
// "any property"?
if (_anySetter != null) {
try {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt));
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
}
}
}
// We hit END_OBJECT, so:
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null; // never gets here
}
return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
}
/*
/**********************************************************
/* Handling for cases where we have property/-ies with
/* external type id
/**********************************************************
*/
protected Object deserializeWithExternalTypeId(JsonParser p, Deserialization
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Context ctxt)
throws IOException
{
if (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt);
}
return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt));
}
protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt,
Object bean)
throws IOException
{
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
final ExternalTypeHandler ext = _externalTypeIdHandler.start();
for (JsonToken t = p.getCurrentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
t = p.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
// [JACKSON-831]: may have property AND be used as external type id:
if (t.isScalarValue()) {
ext.handleTypePropertyValue(p, ctxt, propName, bean);
}
if (activeView != null && !prop.visibleInView(activeView)) {
p.skipChildren();
continue;
}
try {
prop.deserializeAndSet(p, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// ignorable things should be ignored
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(p, ctxt, bean, propName);
continue;
}
// but others are likely to be part of external type id thingy...
if (ext.handlePropertyValue(p, ctxt, propName, bean)) {
continue;
}
// if not, the usual fallback handling:
if (_anySetter != null) {
try {
_anySetter.deserializeAndSet(p, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// Unknown: let's call handler method
handleUnknownProperty(p, ctxt, bean, propName);
}
// and when we get this far, let's try finalizing the deal:
return ext.complete(p, ctxt, bean);
}
@SuppressWarnings("resource")
protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
throws IOException
{
final ExternalTypeHandler ext = _externalTypeIdHandler.start();
final PropertyBasedCreator creator = _propertyBasedCreator;
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
TokenBuffer tokens = new TokenBuffer(p);
tokens.writeStartObject();
JsonToken t = p.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// first: let's check to see if this might be part of value with external type id:
if (ext.handlePropertyValue(p, ctxt, propName, buffer)) {
;
} else {
// Last creator property to set?
Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; // never gets here
}
// if so, need to copy all remaining tokens into buffer
while (t == JsonToken.FIELD_NAME) {
p.nextToken(); // to skip name
tokens.copyCurrentStructure(p);
t = p.nextToken();
}
if (bean.getClass() != _beanType.getRawClass()) {
// !!! 08-Jul-2011, tatu: Could probably support; but for now
// it's too complicated, so bail out
throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
}
return ext.complete(p, ctxt, bean);
}
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(p, ctxt));
continue;
}
// external type id (or property that depends on it)?
if (ext.handlePropertyValue(p, ctxt, propName, null)) {
continue;
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
/**
* Intermediate base class for limited number of scalar types
* that should never include type information. These are "native"
* types that are default mappings for corresponding JSON scalar
* types: {@link java.lang.String}, {@link java.lang.Integer},
* {@link java.lang.Double} and {@link java.lang.Boolean}.
*/
@SuppressWarnings("serial")
public abstract class NonTypedScalarSerializerBase<T>
extends StdScalarSerializer<T>
{
protected NonTypedScalarSerializerBase(Class<T> t) {
super(t);
}
@Override
public final void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer) throws IOException
{
// no type info, just regular serialization
serialize(value, jgen, provider);
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>, locate {@link JsonDeserializer} to use, and
* call it with JSON data to deserializer (which does not contain
* type information).
*/
public abstract Object deserializeTypedFromObject(JsonParser jp, DeserializationContext ctxt) throws IOException;
/**
* Method called to let this type deserializer handle
* deserialization of "typed" object, when value itself
* is serialized as JSON Array (regardless of Java type).
* Method needs to figure out intended
* polymorphic type, locate {@link JsonDeserializer} to use, and
* call it with JSON data to deserializer (which does not contain
* type information).
*/
public abstract Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) throws IOException;
/**
* Method called to let this type deserializer handle
* deserialization of "typed" object, when value itself
* is serialized as a scalar JSON value (something other
* than Array or Object), regardless of Java type.
* Method needs to figure out intended
* polymorphic type, locate {@link JsonDeserializer} to use, and
* call it with JSON data to deserializer (which does not contain
* type information).
*/
public abstract Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) throws IOException;
/**
* Method called to let this type deserializer handle
* deserialization of "typed" object, when value itself
* may have been serialized using any kind of JSON value
* (Array, Object, scalar). Should only be called if JSON
* serialization is polymorphic (not Java type); for example when
* using JSON node representation, or "untyped" Java object
* (which may be Map, Collection, wrapper/primitive etc).
*/
public abstract Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) throws IOException;
/*
/**********************************************************
/* Shared helper methods
/**********************************************************
*/
/**
* Helper method used to check if given parser might be pointing to
* a "natural" value, and one that would be acceptable as the
* result value (compatible with declared base type)
*/
public static Object deserializeIfNatural(JsonParser jp, DeserializationContext ctxt, JavaType baseType) throws IOException {
return deserializeIfNatural(jp, ctxt, baseType.getRawClass());
}
@SuppressWarnings("incomplete-switch")
public static Object deserializeIfNatural(JsonParser jp, DeserializationContext ctxt, Class<?> base) throws IOException
{
JsonToken t = jp.getCurrentToken();
if (t == null) {
return null;
}
switch (t) {
case VALUE_STRING:
if (base.isAssignableFrom(String.class
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Readers);
}
/**
* Factory method used to create {@link MappingIterator} instances;
* either default, or custom subtype.
*
* @since 2.5
*/
protected <T> MappingIterator<T> _newIterator(JavaType valueType,
JsonParser parser, DeserializationContext ctxt,
JsonDeserializer<?> deser, boolean parserManaged, Object valueToUpdate)
{
return new MappingIterator<T>(valueType, parser, ctxt,
deser, parserManaged, valueToUpdate);
}
/*
/**********************************************************
/* Methods sub-classes may choose to override, if customized
/* initialization is needed.
/**********************************************************
*/
/**
* NOTE: changed from static to non-static in 2.5; unfortunate but
* necessary change to support overridability
*/
protected JsonToken _initForReading(JsonParser p) throws IOException
{
if (_schema != null) {
p.setSchema(_schema);
}
_config.initialize(p); // since 2.5
/* First: must point to a token; if not pointing to one, advance.
* This occurs before first read from JsonParser, as well as
* after clearing of current token.
*/
JsonToken t = p.getCurrentToken();
if (t == null) { // and then we must get something...
t = p.nextToken();
if (t == null) {
// Throw mapping exception, since it's failure to map, not an actual parsing problem
throw JsonMappingException.from(p, "No content to map due to end-of-input");
}
}
return t;
}
/**
* Alternative to {@link #_initForReading(JsonParser)} used in cases where reading
* of multiple values means that we may or may not want to advance the stream,
* but need to do other initialization.
*<p>
* Base implementation only sets configured {@link FormatSchema}, if any, on parser.
*
* @since 2.5
*/
protected void _initForMultiRead(JsonParser p) throws IOException {
if (_schema != null) {
p.setSchema(_schema);
}
_config.initialize(p); // since 2.5
}
/*
/**********************************************************
/* Life-cycle, fluent factory methods for DeserializationFeatures
/**********************************************************
*/
/**
* Method for constructing a new reader instance that is configured
* with specified feature enabled.
*/
public ObjectReader with(DeserializationFeature feature) {
return _with(_config.with(feature));
}
/**
* Method for constructing a new reader instance that is configured
*
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> Use {@link #forType(TypeReference)} instead
*/
@Deprecated
public ObjectReader withType(TypeReference<?> valueTypeRef) {
return forType(_config.getTypeFactory().constructType(valueTypeRef.getType()));
}
/**
* Method for constructing a new instance with configuration that
* updates passed Object (as root value), instead of constructing
* a new value.
*<p>
* Note that the method does NOT change state of this reader, but
* rather construct and returns a newly configured instance.
*/
public ObjectReader withValueToUpdate(Object value)
{
if (value == _valueToUpdate) return this;
if (value == null) {
throw new IllegalArgumentException("cat not update null value");
}
JavaType t;
/* no real benefit from pre-fetching, as updating readers are much
* less likely to be reused, and value type may also be forced
* with a later chained call...
*/
if (_valueType == null) {
t = _config.constructType(value.getClass());
} else {
t = _valueType;
}
return _new(this, _config, t, _rootDeserializer, value,
_schema, _injectableValues, _dataFormatReaders);
}
/**
* Method for constructing a new instance with configuration that
* uses specified View for filtering.
*<p>
* Note that the method does NOT change state of this reader, but
* rather construct and returns a newly configured instance.
*/
public ObjectReader withView(Class<?> activeView) {
return _with(_config.withView(activeView));
}
public ObjectReader with(Locale l) {
return _with(_config.with(l));
}
public ObjectReader with(TimeZone tz) {
return _with(_config.with(tz));
}
public ObjectReader withHandler(DeserializationProblemHandler h) {
return _with(_config.withHandler(h));
}
public ObjectReader with(Base64Variant defaultBase64) {
return _with(_config.with(defaultBase64));
}
/**
* Fluent factory method for constructing a reader that will try to
* auto-detect underlying data format, using specified list of
* {@link JsonFactory} instances, and default {@link DataFormatReaders} settings
* (for customized {@link DataFormatReaders}, you can construct instance yourself).
* to construct appropriate {@link JsonParser} for actual parsing.
*<p>
* Note: since format detection only works with byte sources, it is possible to
* get a failure from some 'readValue()' methods. Also, if input can not be
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
/**********************************************************
*/
/**
* Actual implementation of value reading+binding operation.
*/
protected Object _bind(JsonParser jp, Object valueToUpdate) throws IOException
{
/* First: may need to read the next token, to initialize state (either
* before first read from parser, or after previous token has been cleared)
*/
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
if (valueToUpdate == null) {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
result = _findRootDeserializer(ctxt, _valueType).getNullValue();
} else {
result = valueToUpdate;
}
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = valueToUpdate;
} else { // pointing to event other than null
DeserializationContext ctxt = createDeserializationContext(jp, _config);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, _valueType);
if (_unwrapRoot) {
result = _unwrapAndDeserialize(jp, ctxt, _valueType, deser);
} else {
if (valueToUpdate == null) {
result = deser.deserialize(jp, ctxt);
} else {
deser.deserialize(jp, ctxt, valueToUpdate);
result = valueToUpdate;
}
}
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
}
protected Object _bindAndClose(JsonParser jp, Object valueToUpdate) throws IOException
{
try {
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
if (valueToUpdate == null) {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
result = _findRootDeserializer(ctxt, _valueType).getNullValue();
} else {
result = valueToUpdate;
}
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = valueToUpdate;
} else {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, _valueType);
if (_unwrapRoot) {
result = _unwrapAndDeserialize(jp, ctxt, _valueType, deser);
} else {
if (valueToUpdate == null) {
result = deser.deserialize(jp, ctxt);
} else {
deser.deserialize(jp, ctxt, valueToUpdate);
result = valueToUpdate;
}
}
}
return result;
} finally {
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> try {
jp.close();
} catch (IOException ioe) { }
}
}
protected JsonNode _bindAndCloseAsTree(JsonParser jp) throws IOException {
try {
return _bindAsTree(jp);
} finally {
try {
jp.close();
} catch (IOException ioe) { }
}
}
protected JsonNode _bindAsTree(JsonParser jp) throws IOException
{
JsonNode result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL || t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = NullNode.instance;
} else {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
JsonDeserializer<Object> deser = _findTreeDeserializer(ctxt);
if (_unwrapRoot) {
result = (JsonNode) _unwrapAndDeserialize(jp, ctxt, JSON_NODE_TYPE, deser);
} else {
result = (JsonNode) deser.deserialize(jp, ctxt);
}
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
}
/**
* @since 2.1
*/
protected <T> MappingIterator<T> _bindAndReadValues(JsonParser p, Object valueToUpdate) throws IOException
{
_initForMultiRead(p);
p.nextToken();
DeserializationContext ctxt = createDeserializationContext(p, _config);
return _newIterator(_valueType, p, ctxt,
_findRootDeserializer(ctxt, _valueType), true, _valueToUpdate);
}
protected Object _unwrapAndDeserialize(JsonParser jp, DeserializationContext ctxt,
JavaType rootType, JsonDeserializer<Object> deser) throws IOException
{
String expName = _config.getRootName();
if (expName == null) {
PropertyName pname = _rootNames.findRootName(rootType, _config);
expName = pname.getSimpleName();
}
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw JsonMappingException.from(jp, "Current token not START_OBJECT (needed to unwrap root name '"
+expName+"'), but "+jp.getCurrentToken());
}
if (jp.nextToken() != JsonToken.FIELD_NAME) {
throw JsonMappingException.from(jp, "Current token not FIELD_NAME (to contain expected root name '"
+expName+"'), but "+jp.getCurrentToken());
}
String actualName = jp.getCurrentName();
if (!expName.equals(actualName)) {
throw JsonMappingException.from(jp, "Root name
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
_accessorMethod = valueMethod;
_valueSerializer = (JsonSerializer<Object>) ser;
_property = null;
_forceTypeInformation = true; // gets reconsidered when we are contextualized
}
@SuppressWarnings("unchecked")
public JsonValueSerializer(JsonValueSerializer src, BeanProperty property,
JsonSerializer<?> ser, boolean forceTypeInfo)
{
super(_notNullClass(src.handledType()));
_accessorMethod = src._accessorMethod;
_valueSerializer = (JsonSerializer<Object>) ser;
_property = property;
_forceTypeInformation = forceTypeInfo;
}
@SuppressWarnings("unchecked")
private final static Class<Object> _notNullClass(Class<?> cls) {
return (cls == null) ? Object.class : (Class<Object>) cls;
}
public JsonValueSerializer withResolved(BeanProperty property,
JsonSerializer<?> ser, boolean forceTypeInfo)
{
if (_property == property && _valueSerializer == ser
&& forceTypeInfo == _forceTypeInformation) {
return this;
}
return new JsonValueSerializer(this, property, ser, forceTypeInfo);
}
/*
/**********************************************************
/* Post-processing
/**********************************************************
*/
/**
* We can try to find the actual serializer for value, if we can
* statically figure out what the result type must be.
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
JsonSerializer<?> ser = _valueSerializer;
if (ser == null) {
/* Can only assign serializer statically if the declared type is final:
* if not, we don't really know the actual type until we get the instance.
*/
// 10-Mar-2010, tatu: Except if static typing is to be used
if (provider.isEnabled(MapperFeature.USE_STATIC_TYPING)
|| Modifier.isFinal(_accessorMethod.getReturnType().getModifiers())) {
JavaType t = provider.constructType(_accessorMethod.getGenericReturnType());
// false -> no need to cache
/* 10-Mar-2010, tatu: Ideally we would actually separate out type
* serializer from value serializer; but, alas, there's no access
* to serializer factory at this point...
*/
// 05-Sep-2013, tatu: I _think_ this can be considered a primary property...
ser = provider.findPrimaryPropertySerializer(t, property);
/* 09-Dec-2010, tatu: Turns out we must add special handling for
* cases where "
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>native" (aka "natural") type is being serialized,
* using standard serializer
*/
boolean forceTypeInformation = isNaturalTypeWithStdHandling(t.getRawClass(), ser);
return withResolved(property, ser, forceTypeInformation);
}
} else {
// 05-Sep-2013, tatu: I _think_ this can be considered a primary property...
ser = provider.handlePrimaryContextualization(ser, property);
return withResolved(property, ser, _forceTypeInformation);
}
return this;
}
/*
/**********************************************************
/* Actual serialization
/**********************************************************
*/
@Override
public void serialize(Object bean, JsonGenerator jgen, SerializerProvider prov) throws IOException
{
try {
Object value = _accessorMethod.invoke(bean);
if (value == null) {
prov.defaultSerializeNull(jgen);
return;
}
JsonSerializer<Object> ser = _valueSerializer;
if (ser == null) {
Class<?> c = value.getClass();
/* 10-Mar-2010, tatu: Ideally we would actually separate out type
* serializer from value serializer; but, alas, there's no access
* to serializer factory at this point...
*/
// let's cache it, may be needed soon again
ser = prov.findTypedValueSerializer(c, true, _property);
}
ser.serialize(value, jgen, prov);
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t = e;
// Need to unwrap this specific type, to see infinite recursion...
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors shouldn't be wrapped (and often can't, as well)
if (t instanceof Error) {
throw (Error) t;
}
// let's try to indicate the path best we can...
throw JsonMappingException.wrapWithPath(t, bean, _accessorMethod.getName() + "()");
}
}
@Override
public void serializeWithType(Object bean, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer0) throws IOException
{
// Regardless of other parts, first need to find value to serialize:
Object value = null;
try {
value = _accessorMethod.invoke(bean);
// and if we got null, can also just write it directly
if (value == null) {
provider.defaultSerializeNull(jgen);
return;
}
JsonSerializer<Object> ser = _value
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>Serializer;
if (ser == null) { // already got a serializer? fabulous, that be easy...
// ser = provider.findTypedValueSerializer(value.getClass(), true, _property);
ser = provider.findValueSerializer(value.getClass(), _property);
} else {
/* 09-Dec-2010, tatu: To work around natural type's refusal to add type info, we do
* this (note: type is for the wrapper type, not enclosed value!)
*/
if (_forceTypeInformation) {
typeSer0.writeTypePrefixForScalar(bean, jgen);
ser.serialize(value, jgen, provider);
typeSer0.writeTypeSuffixForScalar(bean, jgen);
return;
}
}
/* 13-Feb-2013, tatu: Turns out that work-around should NOT be required
* at all; it would not lead to correct behavior (as per #167).
*/
// and then redirect type id lookups
// TypeSerializer typeSer = new TypeSerializerWrapper(typeSer0, bean);
ser.serializeWithType(value, jgen, provider, typeSer0);
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t = e;
// Need to unwrap this specific type, to see infinite recursion...
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors shouldn't be wrapped (and often can't, as well)
if (t instanceof Error) {
throw (Error) t;
}
// let's try to indicate the path best we can...
throw JsonMappingException.wrapWithPath(t, bean, _accessorMethod.getName() + "()");
}
}
@SuppressWarnings("deprecation")
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
if (_valueSerializer instanceof SchemaAware) {
return ((SchemaAware)_valueSerializer).getSchema(provider, null);
}
return com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonSerializer<Object> ser = _valueSerializer;
if (ser == null) {
if (typeHint == null) {
if (_property != null) {
typeHint = _property.getType();
}
if (typeHint == null) {
typeHint = visitor.
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> (ExceptionInInitializerError e) {
throw wrapException(e);
}
throw ctxt.mappingException("Can not instantiate value of type "+getValueTypeDesc()
+" from Boolean value ("+value+"); no single-boolean/Boolean-arg constructor/factory method");
}
/*
/**********************************************************
/* Extended API: configuration mutators, accessors
/**********************************************************
*/
@Override
public AnnotatedWithParams getDelegateCreator() {
return _delegateCreator;
}
@Override
public AnnotatedWithParams getDefaultCreator() {
return _defaultCreator;
}
@Override
public AnnotatedWithParams getWithArgsCreator() {
return _withArgsCreator;
}
@Override
public AnnotatedParameter getIncompleteParameter() {
return _incompleteParameter;
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected JsonMappingException wrapException(Throwable t)
{
while (t.getCause() != null) {
t = t.getCause();
}
if (t instanceof JsonMappingException) {
return (JsonMappingException) t;
}
return new JsonMappingException("Instantiation of "+getValueTypeDesc()+" value failed: "+t.getMessage(), t);
}
}
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> * Usually this can be defined by using
* {@link com.fasterxml.jackson.annotation.JsonBackReference}
*/
,BACK_REFERENCE
;
}
private final Type _type;
private final String _name;
public ReferenceProperty(Type t, String n) {
_type = t;
_name = n;
}
public static ReferenceProperty managed(String name) { return new ReferenceProperty(Type.MANAGED_REFERENCE, name); }
public static ReferenceProperty back(String name) { return new ReferenceProperty(Type.BACK_REFERENCE, name); }
public Type getType() { return _type; }
public String getName() { return _name; }
public boolean isManagedReference() { return _type == Type.MANAGED_REFERENCE; }
public boolean isBackReference() { return _type == Type.BACK_REFERENCE; }
}
/*
/**********************************************************
/* Factory methods
/**********************************************************
*/
/**
* Factory method for accessing "no operation" implementation
* of introspector: instance that will never find any annotation-based
* configuration.
*/
public static AnnotationIntrospector nopInstance() {
return NopAnnotationIntrospector.instance;
}
public static AnnotationIntrospector pair(AnnotationIntrospector a1, AnnotationIntrospector a2) {
return new AnnotationIntrospectorPair(a1, a2);
}
/*
/**********************************************************
/* Access to possibly chained introspectors (1.7)
/**********************************************************
*/
/**
* Method that can be used to collect all "real" introspectors that
* this introspector contains, if any; or this introspector
* if it is not a container. Used to get access to all container
* introspectors in their priority order.
*<p>
* Default implementation returns a Singleton list with this introspector
* as contents.
* This usually works for sub-classes, except for proxy or delegating "container
* introspectors" which need to override implementation.
*/
public Collection<AnnotationIntrospector> allIntrospectors() {
return Collections.singletonList(this);
}
/**
* Method that can be used to collect all "real" introspectors that
* this introspector contains, if any; or this introspector
* if it is not a container. Used to get access to all container
* introspectors in their priority order.
*<p>
* Default implementation adds this introspector in result; this usually
* works for sub-classes, except for proxy or delegating "container
* introspectors" which need to override implementation.
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> | _hasNativeObjectIds;
JsonParser jp = other.asParser();
while (jp.nextToken() != null) {
copyCurrentStructure(jp);
}
return this;
}
/**
* Helper method that will write all contents of this buffer
* using given {@link JsonGenerator}.
*<p>
* Note: this method would be enough to implement
* <code>JsonSerializer</code> for <code>TokenBuffer</code> type;
* but we can not have upwards
* references (from core to mapper package); and as such we also
* can not take second argument.
*/
public void serialize(JsonGenerator jgen)
throws IOException, JsonGenerationException
{
Segment segment = _first;
int ptr = -1;
final boolean checkIds = _mayHaveNativeIds;
boolean hasIds = checkIds && (segment.hasIds());
while (true) {
if (++ptr >= Segment.TOKENS_PER_SEGMENT) {
ptr = 0;
segment = segment.next();
if (segment == null) break;
hasIds = checkIds && (segment.hasIds());
}
JsonToken t = segment.type(ptr);
if (t == null) break;
if (hasIds) {
Object id = segment.findObjectId(ptr);
if (id != null) {
jgen.writeObjectId(id);
}
id = segment.findTypeId(ptr);
if (id != null) {
jgen.writeTypeId(id);
}
}
// Note: copied from 'copyCurrentEvent'...
switch (t) {
case START_OBJECT:
jgen.writeStartObject();
break;
case END_OBJECT:
jgen.writeEndObject();
break;
case START_ARRAY:
jgen.writeStartArray();
break;
case END_ARRAY:
jgen.writeEndArray();
break;
case FIELD_NAME:
{
// 13-Dec-2010, tatu: Maybe we should start using different type tokens to reduce casting?
Object ob = segment.get(ptr);
if (ob instanceof SerializableString) {
jgen.writeFieldName((SerializableString) ob);
} else {
jgen.writeFieldName((String) ob);
}
}
break;
case VALUE_STRING:
{
Object ob = segment.get(ptr);
if (ob instanceof SerializableString) {
jgen.writeString((SerializableString) ob);
} else {
jgen.writeString((String) ob);
}
}
break;
case VALUE_NUMBER_
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>INT:
{
Object n = segment.get(ptr);
if (n instanceof Integer) {
jgen.writeNumber((Integer) n);
} else if (n instanceof BigInteger) {
jgen.writeNumber((BigInteger) n);
} else if (n instanceof Long) {
jgen.writeNumber((Long) n);
} else if (n instanceof Short) {
jgen.writeNumber((Short) n);
} else {
jgen.writeNumber(((Number) n).intValue());
}
}
break;
case VALUE_NUMBER_FLOAT:
{
Object n = segment.get(ptr);
if (n instanceof Double) {
jgen.writeNumber(((Double) n).doubleValue());
} else if (n instanceof BigDecimal) {
jgen.writeNumber((BigDecimal) n);
} else if (n instanceof Float) {
jgen.writeNumber(((Float) n).floatValue());
} else if (n == null) {
jgen.writeNull();
} else if (n instanceof String) {
jgen.writeNumber((String) n);
} else {
throw new JsonGenerationException("Unrecognized value type for VALUE_NUMBER_FLOAT: "+n.getClass().getName()+", can not serialize");
}
}
break;
case VALUE_TRUE:
jgen.writeBoolean(true);
break;
case VALUE_FALSE:
jgen.writeBoolean(false);
break;
case VALUE_NULL:
jgen.writeNull();
break;
case VALUE_EMBEDDED_OBJECT:
jgen.writeObject(segment.get(ptr));
break;
default:
throw new RuntimeException("Internal error: should never end up through this code path");
}
}
}
/**
* Helper method used by standard deserializer.
*
* @since 2.3
*/
public TokenBuffer deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
if (jp.getCurrentTokenId() != JsonToken.FIELD_NAME.id()) {
copyCurrentStructure(jp);
return this;
}
/* 28-Oct-2014, tatu: As per #592, need to support a special case of starting from
* FIELD_NAME, which is taken to mean that we are missing START_OBJECT, but need
* to assume one did exist.
*/
JsonToken t;
writeStartObject();
do {
copyCurrentStructure(jp);
} while ((t = jp.nextToken()) == JsonToken.FIELD_NAME);
if (t != JsonToken.END_OBJECT) {
throw ctxt
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>.mappingException("Expected END_OBJECT after copying contents of a JsonParser into TokenBuffer, got "+t);
}
writeEndObject();
return this;
}
@Override
@SuppressWarnings("resource")
public String toString()
{
// Let's print up to 100 first tokens...
final int MAX_COUNT = 100;
StringBuilder sb = new StringBuilder();
sb.append("[TokenBuffer: ");
/*
sb.append("NativeTypeIds=").append(_hasNativeTypeIds).append(",");
sb.append("NativeObjectIds=").append(_hasNativeObjectIds).append(",");
*/
JsonParser jp = asParser();
int count = 0;
final boolean hasNativeIds = _hasNativeTypeIds || _hasNativeObjectIds;
while (true) {
JsonToken t;
try {
t = jp.nextToken();
if (t == null) break;
if (hasNativeIds) {
_appendNativeIds(sb);
}
if (count < MAX_COUNT) {
if (count > 0) {
sb.append(", ");
}
sb.append(t.toString());
if (t == JsonToken.FIELD_NAME) {
sb.append('(');
sb.append(jp.getCurrentName());
sb.append(')');
}
}
} catch (IOException ioe) { // should never occur
throw new IllegalStateException(ioe);
}
++count;
}
if (count >= MAX_COUNT) {
sb.append(" ... (truncated ").append(count-MAX_COUNT).append(" entries)");
}
sb.append(']');
return sb.toString();
}
private final void _appendNativeIds(StringBuilder sb)
{
Object objectId = _last.findObjectId(_appendAt-1);
if (objectId != null) {
sb.append("[objectId=").append(String.valueOf(objectId)).append(']');
}
Object typeId = _last.findTypeId(_appendAt-1);
if (typeId != null) {
sb.append("[typeId=").append(String.valueOf(typeId)).append(']');
}
}
/*
/**********************************************************
/* JsonGenerator implementation: configuration
/**********************************************************
*/
@Override
public JsonGenerator enable(Feature f) {
_generatorFeatures |= f.getMask();
return this;
}
@Override
public JsonGenerator disable(Feature f) {
_generatorFeatures &= ~f.getMask();
return this;
}
//public JsonGenerator configure(SerializationFeature f, boolean state) { }
@Override
public boolean isEnabled(
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS>
}
@Override
public void writeObjectId(Object id) {
_objectId = id;
_hasNativeId = true;
}
/*
/**********************************************************
/* JsonGenerator implementation; pass-through copy
/**********************************************************
*/
@Override
public void copyCurrentEvent(JsonParser jp) throws IOException, JsonProcessingException
{
if (_mayHaveNativeIds) {
_checkNativeIds(jp);
}
switch (jp.getCurrentToken()) {
case START_OBJECT:
writeStartObject();
break;
case END_OBJECT:
writeEndObject();
break;
case START_ARRAY:
writeStartArray();
break;
case END_ARRAY:
writeEndArray();
break;
case FIELD_NAME:
writeFieldName(jp.getCurrentName());
break;
case VALUE_STRING:
if (jp.hasTextCharacters()) {
writeString(jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength());
} else {
writeString(jp.getText());
}
break;
case VALUE_NUMBER_INT:
switch (jp.getNumberType()) {
case INT:
writeNumber(jp.getIntValue());
break;
case BIG_INTEGER:
writeNumber(jp.getBigIntegerValue());
break;
default:
writeNumber(jp.getLongValue());
}
break;
case VALUE_NUMBER_FLOAT:
switch (jp.getNumberType()) {
case BIG_DECIMAL:
writeNumber(jp.getDecimalValue());
break;
case FLOAT:
writeNumber(jp.getFloatValue());
break;
default:
writeNumber(jp.getDoubleValue());
}
break;
case VALUE_TRUE:
writeBoolean(true);
break;
case VALUE_FALSE:
writeBoolean(false);
break;
case VALUE_NULL:
writeNull();
break;
case VALUE_EMBEDDED_OBJECT:
writeObject(jp.getEmbeddedObject());
break;
default:
throw new RuntimeException("Internal error: should never end up through this code path");
}
}
@Override
public void copyCurrentStructure(JsonParser jp) throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
// Let's handle field-name separately first
if (t == JsonToken.FIELD_NAME) {
if (_mayHaveNativeIds) {
_checkNativeIds(jp);
}
writeFieldName(jp.getCurrentName());
t = jp.nextToken();
// fall-through to copy the associated value
}
if (_mayHaveNativeIds) {
_checkNativeIds(jp);
}
switch (t
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> str = getText();
if (str == null) {
return null;
}
ByteArrayBuilder builder = _byteBuilder;
if (builder == null) {
_byteBuilder = builder = new ByteArrayBuilder(100);
} else {
_byteBuilder.reset();
}
_decodeBase64(str, builder, b64variant);
return builder.toByteArray();
}
@Override
public int readBinaryValue(Base64Variant b64variant, OutputStream out)
throws IOException, JsonParseException
{
byte[] data = getBinaryValue(b64variant);
if (data != null) {
out.write(data, 0, data.length);
return data.length;
}
return 0;
}
/*
/**********************************************************
/* Public API, native ids
/**********************************************************
*/
@Override
public boolean canReadObjectId() {
return _hasNativeObjectIds;
}
@Override
public boolean canReadTypeId() {
return _hasNativeTypeIds;
}
@Override
public Object getTypeId() {
return _segment.findTypeId(_segmentPtr);
}
@Override
public Object getObjectId() {
return _segment.findObjectId(_segmentPtr);
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected final Object _currentObject() {
return _segment.get(_segmentPtr);
}
protected final void _checkIsNumber() throws JsonParseException
{
if (_currToken == null || !_currToken.isNumeric()) {
throw _constructError("Current token ("+_currToken+") not numeric, can not use numeric value accessors");
}
}
@Override
protected void _handleEOF() throws JsonParseException {
_throwInternal();
}
}
/**
* Individual segment of TokenBuffer that can store up to 16 tokens
* (limited by 4 bits per token type marker requirement).
* Current implementation uses fixed length array; could alternatively
* use 16 distinct fields and switch statement (slightly more efficient
* storage, slightly slower access)
*/
protected final static class Segment
{
public final static int TOKENS_PER_SEGMENT = 16;
/**
* Static array used for fast conversion between token markers and
* matching {@link JsonToken} instances
*/
private final static JsonToken[] TOKEN_TYPES_BY_INDEX;
static {
// ... here we know that there are <= 15 values in JsonToken enum
TOKEN_TYPES_BY_INDEX = new JsonToken[16];
JsonToken[] t = JsonToken.values();
// and reserve entry 0
JacksonDatabind, 35
<FILEB>
<CHANGES>
JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
<CHANGEE>
<CHANGES>
} else if (t!= JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
<FILEE>
<FILEB>
/***************************************************************
*/
/**
* Method that handles type information wrapper, locates actual
* subtype deserializer to use, and calls it to do actual
* deserialization.
*/
@SuppressWarnings("resource")
private final Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// 02-Aug-2013, tatu: May need to use native type ids
if (p.canReadTypeId()) {
Object typeId = p.getTypeId();
if (typeId != null) {
return _deserializeWithNativeTypeId(p, ctxt, typeId);
}
}
// first, sanity checks
<CHANGES>
if (p.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
"need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
}
<CHANGEE>
// should always get field name, but just in case...
if (p.nextToken() != JsonToken.FIELD_NAME) {
throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
"need JSON String that contains type id (for subtype of "+baseTypeName()+")");
}
<CHANGES>
<CHANGEE>
final String typeId = p.getText();
JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
p.nextToken();
// Minor complication: we may need to merge type id in?
if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
// but what if there's nowhere to add it in? Error? Or skip? For now, skip.
TokenBuffer tb = new TokenBuffer(null, false);
tb.writeStartObject(); // recreate START_OBJECT
tb.writeFieldName(_typePropertyName);
tb.writeString(typeId);
p = JsonParserSequence.createFlattened(tb.asParser(p), p);
p.nextToken();
<FILEE>
<SCANS> for "not available"
System.arraycopy(t, 1, TOKEN_TYPES_BY_INDEX, 1, Math.min(15, t.length - 1));
}
// // // Linking
protected Segment _next;
// // // State
/**
* Bit field used to store types of buffered tokens; 4 bits per token.
* Value 0 is reserved for "not in use"
*/
protected long _tokenTypes;
// Actual tokens
protected final Object[] _tokens = new Object[TOKENS_PER_SEGMENT];
/**
* Lazily constructed Map for storing native type and object ids, if any
*/
protected TreeMap<Integer,Object> _nativeIds;
public Segment() { }
// // // Accessors
public JsonToken type(int index)
{
long l = _tokenTypes;
if (index > 0) {
l >>= (index << 2);
}
int ix = ((int) l) & 0xF;
return TOKEN_TYPES_BY_INDEX[ix];
}
public int rawType(int index)
{
long l = _tokenTypes;
if (index > 0) {
l >>= (index << 2);
}
int ix = ((int) l) & 0xF;
return ix;
}
public Object get(int index) {
return _tokens[index];
}
public Segment next() { return _next; }
/**
* Accessor for checking whether this segment may have native
* type or object ids.
*/
public boolean hasIds() {
return _nativeIds != null;
}
// // // Mutators
public Segment append(int index, JsonToken tokenType)
{
if (index < TOKENS_PER_SEGMENT) {
set(index, tokenType);
return null;
}
_next = new Segment();
_next.set(0, tokenType);
return _next;
}
public Segment append(int index, JsonToken tokenType,
Object objectId, Object typeId)
{
if (index < TOKENS_PER_SEGMENT) {
set(index, tokenType, objectId, typeId);
return null;
}
_next = new Segment();
_next.set(0, tokenType, objectId, typeId);
return _next;
}
public Segment append(int index, JsonToken tokenType, Object value)
{
if (index < TOKENS_PER_SEGMENT) {
set(index, tokenType, value);
return null;
}
_next = new Segment();
_next.set